@monokle/validation
Advanced tools
Comparing version 0.25.4 to 0.26.0
@@ -68,2 +68,5 @@ /** | ||
}; | ||
export declare type ExternalSuppression = Suppression & { | ||
guid: string; | ||
}; | ||
export declare type SuppressionKind = 'inSource' | 'external'; | ||
@@ -70,0 +73,0 @@ export declare type SuppressionStatus = 'underReview' | 'accepted' | 'rejected'; |
import { ResourceParser } from './common/resourceParser.js'; | ||
import type { ValidationResponse } from './common/sarif.js'; | ||
import type { Suppression, ValidationResponse } from './common/sarif.js'; | ||
import type { CustomSchema, Incremental, Plugin, Resource } from './common/types.js'; | ||
@@ -55,2 +55,3 @@ import { Config, PluginMap } from './config/parse.js'; | ||
_customSchemas: Set<string>; | ||
_suppressions: Suppression[]; | ||
private _suppressor; | ||
@@ -101,3 +102,3 @@ constructor(loader: PluginLoader, suppressors?: Suppressor[], fallback?: PluginMap); | ||
*/ | ||
preload(config?: Config): Promise<void>; | ||
preload(config?: Config, suppressions?: Suppression[]): Promise<void>; | ||
/** | ||
@@ -117,2 +118,3 @@ * Load the plugin and prepare it. | ||
validate({ resources, incremental, baseline, abortSignal: externalAbortSignal, }: ValidateParams): Promise<ValidationResponse>; | ||
applySuppressions(result: ValidationResponse, resources: Resource[], suppressions?: Suppression[]): Promise<ValidationResponse>; | ||
/** | ||
@@ -119,0 +121,0 @@ * Compares the validation result with a baseline. |
@@ -12,3 +12,3 @@ import { v4 } from 'uuid'; | ||
import { isDefined } from './utils/isDefined.js'; | ||
import { AnnotationSuppressor } from './sarif/suppressions/index.js'; | ||
import { AnnotationSuppressor, FingerprintSuppressor } from './sarif/suppressions/index.js'; | ||
import { SuppressEngine } from './sarif/suppressions/engine.js'; | ||
@@ -27,3 +27,3 @@ export function createMonokleValidator(loader, suppressors, fallback) { | ||
}; | ||
const DEFAULT_SUPPRESSORS = [new AnnotationSuppressor()]; | ||
const DEFAULT_SUPPRESSORS = [new AnnotationSuppressor(), new FingerprintSuppressor()]; | ||
export class MonokleValidator { | ||
@@ -49,2 +49,3 @@ /** | ||
_customSchemas = new Set(); | ||
_suppressions = []; | ||
_suppressor; | ||
@@ -120,4 +121,5 @@ constructor(loader, suppressors = DEFAULT_SUPPRESSORS, fallback = DEFAULT_PLUGIN_MAP) { | ||
*/ | ||
async preload(config) { | ||
async preload(config, suppressions) { | ||
this._config = config; | ||
this._suppressions = suppressions || []; | ||
return this.load(); | ||
@@ -189,6 +191,9 @@ } | ||
// Configure validators | ||
await Promise.allSettled(this._plugins.map(p => p.configure({ | ||
rules: config.rules, | ||
settings: config.settings, | ||
}))); | ||
await Promise.allSettled([ | ||
...this._plugins.map(p => p.configure({ | ||
rules: config.rules, | ||
settings: config.settings, | ||
})), | ||
this._suppressor.preload(this._suppressions), | ||
]); | ||
} | ||
@@ -223,3 +228,2 @@ async doUnload(plugins) { | ||
this.preprocessCustomResourceDefinitions(resources); | ||
new SuppressEngine().preload(); | ||
const allRuns = await Promise.allSettled(validators.map(v => v.validate(resources, { incremental }))); | ||
@@ -249,2 +253,9 @@ throwIfAborted(loadAbortSignal, externalAbortSignal); | ||
} | ||
return this.applySuppressions(result, resources); | ||
} | ||
async applySuppressions(result, resources, suppressions) { | ||
if (suppressions) { | ||
this._suppressions = suppressions; | ||
await this._suppressor.preload(suppressions); | ||
} | ||
await this._suppressor.suppress(result, resources, { | ||
@@ -251,0 +262,0 @@ noInSourceSuppressions: this._config?.settings?.noInSourceSuppressions, |
@@ -1,2 +0,2 @@ | ||
import { ValidationResponse } from '../../common/sarif.js'; | ||
import { Suppression, ValidationResponse } from '../../common/sarif.js'; | ||
import { Suppressor } from './types.js'; | ||
@@ -11,3 +11,3 @@ import type { Resource } from '../../common/types.js'; | ||
constructor(suppressors?: Suppressor[]); | ||
preload(): Promise<PromiseSettledResult<void>[]>; | ||
preload(suppressions: Suppression[]): Promise<PromiseSettledResult<void>[]>; | ||
private getSuppressors; | ||
@@ -14,0 +14,0 @@ /** |
import { AnnotationSuppressor } from './plugins/AnnotationSuppressor.js'; | ||
import keyBy from 'lodash/keyBy.js'; | ||
const DEFAULT_SUPPRESSORS = [new AnnotationSuppressor()]; | ||
import { FingerprintSuppressor } from './plugins/FingerprintSuppressor.js'; | ||
const DEFAULT_SUPPRESSORS = [new AnnotationSuppressor(), new FingerprintSuppressor()]; | ||
export class SuppressEngine { | ||
@@ -9,4 +10,4 @@ suppressors; | ||
} | ||
async preload() { | ||
return Promise.allSettled(this.suppressors.map(s => s.preload())); | ||
async preload(suppressions) { | ||
return Promise.allSettled(this.suppressors.map(s => s.preload(suppressions))); | ||
} | ||
@@ -13,0 +14,0 @@ getSuppressors(options) { |
export * from './types.js'; | ||
export * from './plugins/AnnotationSuppressor.js'; | ||
export * from './plugins/FingerprintSuppressor.js'; |
export * from './types.js'; | ||
export * from './plugins/AnnotationSuppressor.js'; | ||
export * from './plugins/FingerprintSuppressor.js'; |
@@ -1,2 +0,2 @@ | ||
import { Suppression, SuppressionKind, ValidationResult, ValidationRun } from '../../common/sarif.js'; | ||
import { ExternalSuppression, Suppression, SuppressionKind, ValidationResult, ValidationRun } from '../../common/sarif.js'; | ||
import { Resource } from '../../common/types.js'; | ||
@@ -7,6 +7,15 @@ export declare type ResourceApi = { | ||
}; | ||
export interface Suppressor { | ||
export interface Suppressor<S extends Suppression = Suppression> { | ||
kind: SuppressionKind; | ||
preload(): Promise<void>; | ||
preload(suppressions?: S[]): Promise<void>; | ||
suppress(problem: ValidationResult, run: ValidationRun, api: ResourceApi): Suppression[] | Promise<Suppression[]>; | ||
suppressions?: S[]; | ||
} | ||
export interface AnnotationsSuppression extends Suppression { | ||
kind: 'inSource'; | ||
status: 'accepted'; | ||
} | ||
export interface FingerprintSuppression extends ExternalSuppression { | ||
kind: 'external'; | ||
fingerprint: string; | ||
} |
@@ -17,3 +17,3 @@ const DEFAULT_SEED = 1337; | ||
const resource = result.locations[1].logicalLocations?.find(l => l.kind === 'resource')?.fullyQualifiedName; | ||
const yamlPath = result.locations[1].logicalLocations?.find(l => l.kind === 'element')?.name; | ||
const yamlPath = result.locations[1].logicalLocations?.find(l => l.kind === 'element')?.fullyQualifiedName; | ||
const stableIdentifier = `${tool}#${rule}#${resource}#${yamlPath}`; | ||
@@ -20,0 +20,0 @@ return fastHash(stableIdentifier); |
{ | ||
"name": "@monokle/validation", | ||
"version": "0.25.4", | ||
"version": "0.26.0", | ||
"description": "Kubernetes resource validation", | ||
@@ -50,2 +50,3 @@ "author": "Kubeshop", | ||
"devDependencies": { | ||
"@monokle/parser": "*", | ||
"@types/isomorphic-fetch": "0.0.36", | ||
@@ -52,0 +53,0 @@ "@types/lodash": "4.14.185", |
512440
346
12667
11