mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[Config Service] Ignore unknown config on Serverless (#187006)
This commit is contained in:
parent
1a8a905835
commit
00337de019
14 changed files with 161 additions and 1354 deletions
|
@ -7,4 +7,7 @@
|
|||
*/
|
||||
|
||||
export { coreDeprecationProvider } from './src/deprecation';
|
||||
export { ensureValidConfiguration } from './src/ensure_valid_configuration';
|
||||
export {
|
||||
ensureValidConfiguration,
|
||||
type EnsureValidConfigurationParameters,
|
||||
} from './src/ensure_valid_configuration';
|
||||
|
|
|
@ -22,19 +22,19 @@ describe('ensureValidConfiguration', () => {
|
|||
});
|
||||
|
||||
it('returns normally when there is no unused keys and when the config validates', async () => {
|
||||
await expect(ensureValidConfiguration(configService as any)).resolves.toBeUndefined();
|
||||
await expect(ensureValidConfiguration(configService)).resolves.toBeUndefined();
|
||||
|
||||
expect(configService.validate).toHaveBeenCalledWith(undefined);
|
||||
expect(configService.validate).toHaveBeenCalledWith({ logDeprecations: true });
|
||||
});
|
||||
|
||||
it('forwards parameters to the `validate` method', async () => {
|
||||
await expect(
|
||||
ensureValidConfiguration(configService as any, { logDeprecations: false })
|
||||
ensureValidConfiguration(configService, { logDeprecations: false })
|
||||
).resolves.toBeUndefined();
|
||||
expect(configService.validate).toHaveBeenCalledWith({ logDeprecations: false });
|
||||
|
||||
await expect(
|
||||
ensureValidConfiguration(configService as any, { logDeprecations: true })
|
||||
ensureValidConfiguration(configService, { logDeprecations: true })
|
||||
).resolves.toBeUndefined();
|
||||
expect(configService.validate).toHaveBeenCalledWith({ logDeprecations: true });
|
||||
});
|
||||
|
@ -44,7 +44,7 @@ describe('ensureValidConfiguration', () => {
|
|||
throw new Error('some message');
|
||||
});
|
||||
|
||||
await expect(ensureValidConfiguration(configService as any)).rejects.toMatchInlineSnapshot(
|
||||
await expect(ensureValidConfiguration(configService)).rejects.toMatchInlineSnapshot(
|
||||
`[Error: some message]`
|
||||
);
|
||||
});
|
||||
|
@ -57,7 +57,7 @@ describe('ensureValidConfiguration', () => {
|
|||
});
|
||||
|
||||
try {
|
||||
await ensureValidConfiguration(configService as any);
|
||||
await ensureValidConfiguration(configService);
|
||||
} catch (e) {
|
||||
expect(e).toBeInstanceOf(CriticalError);
|
||||
expect(e.processExitCode).toEqual(78);
|
||||
|
@ -67,18 +67,26 @@ describe('ensureValidConfiguration', () => {
|
|||
it('throws when there are some unused keys', async () => {
|
||||
configService.getUnusedPaths.mockResolvedValue(['some.key', 'some.other.key']);
|
||||
|
||||
await expect(ensureValidConfiguration(configService as any)).rejects.toMatchInlineSnapshot(
|
||||
await expect(ensureValidConfiguration(configService)).rejects.toMatchInlineSnapshot(
|
||||
`[Error: Unknown configuration key(s): "some.key", "some.other.key". Check for spelling errors and ensure that expected plugins are installed.]`
|
||||
);
|
||||
});
|
||||
|
||||
it('does not throw when there are some unused keys and skipUnusedConfigKeysCheck: true', async () => {
|
||||
configService.getUnusedPaths.mockResolvedValue(['some.key', 'some.other.key']);
|
||||
|
||||
await expect(
|
||||
ensureValidConfiguration(configService, { logDeprecations: true, stripUnknownKeys: true })
|
||||
).resolves.toBeUndefined();
|
||||
});
|
||||
|
||||
it('throws a `CriticalError` with the correct processExitCode value', async () => {
|
||||
expect.assertions(2);
|
||||
|
||||
configService.getUnusedPaths.mockResolvedValue(['some.key', 'some.other.key']);
|
||||
|
||||
try {
|
||||
await ensureValidConfiguration(configService as any);
|
||||
await ensureValidConfiguration(configService);
|
||||
} catch (e) {
|
||||
expect(e).toBeInstanceOf(CriticalError);
|
||||
expect(e.processExitCode).toEqual(64);
|
||||
|
@ -88,13 +96,13 @@ describe('ensureValidConfiguration', () => {
|
|||
it('does not throw when all unused keys are included in the ignored paths', async () => {
|
||||
configService.getUnusedPaths.mockResolvedValue(['dev.someDevKey', 'elastic.apm.enabled']);
|
||||
|
||||
await expect(ensureValidConfiguration(configService as any)).resolves.toBeUndefined();
|
||||
await expect(ensureValidConfiguration(configService)).resolves.toBeUndefined();
|
||||
});
|
||||
|
||||
it('throws when only some keys are included in the ignored paths', async () => {
|
||||
configService.getUnusedPaths.mockResolvedValue(['dev.someDevKey', 'some.key']);
|
||||
|
||||
await expect(ensureValidConfiguration(configService as any)).rejects.toMatchInlineSnapshot(
|
||||
await expect(ensureValidConfiguration(configService)).rejects.toMatchInlineSnapshot(
|
||||
`[Error: Unknown configuration key(s): "some.key". Check for spelling errors and ensure that expected plugins are installed.]`
|
||||
);
|
||||
});
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { ConfigService, ConfigValidateParameters } from '@kbn/config';
|
||||
import type { IConfigService, ConfigValidateParameters } from '@kbn/config';
|
||||
import { CriticalError } from '@kbn/core-base-server-internal';
|
||||
|
||||
const ignoredPaths = ['dev.', 'elastic.apm.'];
|
||||
|
@ -14,12 +14,32 @@ const ignoredPaths = ['dev.', 'elastic.apm.'];
|
|||
const invalidConfigExitCode = 78;
|
||||
const legacyInvalidConfigExitCode = 64;
|
||||
|
||||
/**
|
||||
* Parameters for the helper {@link ensureValidConfiguration}
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
export interface EnsureValidConfigurationParameters extends ConfigValidateParameters {
|
||||
/**
|
||||
* Set to `true` to ignore any unknown keys and discard them from the final validated config object.
|
||||
*/
|
||||
stripUnknownKeys?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the entire Kibana configuration object, including the detection of extra keys.
|
||||
* @param configService The {@link IConfigService} instance that has the raw configuration preloaded.
|
||||
* @param params {@link EnsureValidConfigurationParameters | Options} to enable/disable extra edge-cases.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
export async function ensureValidConfiguration(
|
||||
configService: ConfigService,
|
||||
params?: ConfigValidateParameters
|
||||
configService: IConfigService,
|
||||
params: EnsureValidConfigurationParameters = { logDeprecations: true }
|
||||
) {
|
||||
const { stripUnknownKeys, ...validateParams } = params;
|
||||
try {
|
||||
await configService.validate(params);
|
||||
await configService.validate(validateParams);
|
||||
} catch (e) {
|
||||
throw new CriticalError(e.message, 'InvalidConfig', invalidConfigExitCode, e);
|
||||
}
|
||||
|
@ -29,7 +49,7 @@ export async function ensureValidConfiguration(
|
|||
return !ignoredPaths.some((ignoredPath) => unusedPath.startsWith(ignoredPath));
|
||||
});
|
||||
|
||||
if (unusedConfigKeys.length > 0) {
|
||||
if (unusedConfigKeys.length > 0 && !stripUnknownKeys) {
|
||||
const message = `Unknown configuration key(s): ${unusedConfigKeys
|
||||
.map((key) => `"${key}"`)
|
||||
.join(', ')}. Check for spelling errors and ensure that expected plugins are installed.`;
|
||||
|
|
|
@ -256,7 +256,7 @@ export class Server {
|
|||
const environmentSetup = this.environment.setup();
|
||||
|
||||
// Configuration could have changed after preboot.
|
||||
await ensureValidConfiguration(this.configService);
|
||||
await this.ensureValidConfiguration();
|
||||
|
||||
const { uiPlugins, pluginPaths, pluginTree } = this.discoveredPlugins!.standard;
|
||||
const contextServiceSetup = this.context.setup({
|
||||
|
@ -486,6 +486,27 @@ export class Server {
|
|||
this.userProfile.stop();
|
||||
}
|
||||
|
||||
private async ensureValidConfiguration() {
|
||||
try {
|
||||
await ensureValidConfiguration(this.configService);
|
||||
} catch (validationError) {
|
||||
if (this.env.packageInfo.buildFlavor !== 'serverless') {
|
||||
throw validationError;
|
||||
}
|
||||
// When running on serverless, we may allow unknown keys, but stripping them from the final config object.
|
||||
this.configService.setGlobalStripUnknownKeys(true);
|
||||
await ensureValidConfiguration(this.configService, {
|
||||
logDeprecations: true,
|
||||
stripUnknownKeys: true,
|
||||
});
|
||||
this.log
|
||||
.get('config-validation')
|
||||
.error(
|
||||
`Strict config validation failed! Extra unknown keys removed in Serverless-compatible mode. Original error: ${validationError}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private registerCoreContext(coreSetup: InternalCoreSetup) {
|
||||
coreSetup.http.registerRouteHandlerContext<RequestHandlerContext, 'core'>(
|
||||
coreId,
|
||||
|
|
|
@ -29,6 +29,7 @@ const createConfigServiceMock = ({
|
|||
getDeprecatedConfigPath$: jest.fn(),
|
||||
addDynamicConfigPaths: jest.fn(),
|
||||
setDynamicConfigOverrides: jest.fn(),
|
||||
setGlobalStripUnknownKeys: jest.fn(),
|
||||
};
|
||||
|
||||
mocked.atPath.mockReturnValue(new BehaviorSubject(atPath));
|
||||
|
|
|
@ -64,6 +64,8 @@ Every schema instance has a `validate` method that is used to perform a validati
|
|||
* `data: any` - **required**, data to be validated with the schema
|
||||
* `context: Record<string, any>` - **optional**, object whose properties can be referenced by the [context references](#schemacontextref)
|
||||
* `namespace: string` - **optional**, arbitrary string that is used to prefix every error message thrown during validation
|
||||
* `validationOptions: SchemaValidationOptions` - **optional**, global options to modify the default validation behavior
|
||||
* `stripUnknownKeys: boolean` - **optional**, when `true`, it changes the default `unknowns: 'forbid'` to behave like `unknowns: 'ignore'`. This change of behavior only occurs in schemas without an explicit `unknowns` option. Refer to [`schema.object()`](#schemaobject) for more information about the `unknowns` option.
|
||||
|
||||
```typescript
|
||||
const valueSchema = schema.object({
|
||||
|
@ -243,7 +245,7 @@ __Output type:__ `{ [K in keyof TProps]: TypeOf<TProps[K]> } as TObject`
|
|||
__Options:__
|
||||
* `defaultValue: TObject | Reference<TObject> | (() => TObject)` - defines a default value, see [Default values](#default-values) section for more details.
|
||||
* `validate: (value: TObject) => string | void` - defines a custom validator function, see [Custom validation](#custom-validation) section for more details.
|
||||
* `unknowns: 'allow' | 'ignore' | 'forbid'` - indicates whether unknown object properties should be allowed, ignored, or forbidden. It's `forbid` by default.
|
||||
* `unknowns: 'allow' | 'ignore' | 'forbid'` - indicates whether unknown object properties and sub-properties should be allowed, ignored, or forbidden. It is `forbid` by default unless the global validation option `stripUnknownKeys` is set to `true` when calling `validate()`. Refer to [the `validate()` API options](#schema-building-blocks) to learn about `stripUnknownKeys`.
|
||||
|
||||
__Usage:__
|
||||
```typescript
|
||||
|
@ -255,6 +257,7 @@ const valueSchema = schema.object({
|
|||
|
||||
__Notes:__
|
||||
* Using `unknowns: 'allow'` is discouraged and should only be used in exceptional circumstances. Consider using `schema.recordOf()` instead.
|
||||
* Bear in mind that specifying `unknowns: 'allow' | 'ignore' | 'forbid'` applies to the entire tree of sub-objects. If you want this option to apply only to the properties in first level, make sure to override this option by setting a new `unknowns` option in the child `schema.object()`s.
|
||||
* Currently `schema.object()` always has a default value of `{}`, but this may change in the near future. Try to not rely on this behaviour and specify default value explicitly or use `schema.maybe()` if the value is optional.
|
||||
* `schema.object()` also supports a json string as input if it can be safely parsed using `JSON.parse` and if the resulting value is a plain object.
|
||||
|
||||
|
|
|
@ -57,6 +57,7 @@ import {
|
|||
|
||||
export type { AnyType, ConditionalType, TypeOf, Props, SchemaStructureEntry, NullableProps };
|
||||
export { ObjectType, Type };
|
||||
export type { SchemaValidationOptions } from './src/types';
|
||||
export { ByteSizeValue } from './src/byte_size_value';
|
||||
export { SchemaTypeError, ValidationError } from './src/errors';
|
||||
export { isConfigSchema } from './src/typeguards';
|
||||
|
|
|
@ -6,8 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
export type { TypeOptions } from './type';
|
||||
export type { SchemaStructureEntry } from './type';
|
||||
export type { SchemaStructureEntry, SchemaValidationOptions, TypeOptions } from './type';
|
||||
export { Type } from './type';
|
||||
export { AnyType } from './any_type';
|
||||
export type { ArrayOptions } from './array_type';
|
||||
|
|
|
@ -338,12 +338,32 @@ test('allow and remove unknown keys when unknowns = `ignore`', () => {
|
|||
});
|
||||
});
|
||||
|
||||
test('unknowns = `ignore` affects only own keys', () => {
|
||||
test('unknowns = `ignore` is recursive if no explicit preferences in sub-keys', () => {
|
||||
const type = schema.object(
|
||||
{ foo: schema.object({ bar: schema.string() }) },
|
||||
{ unknowns: 'ignore' }
|
||||
);
|
||||
|
||||
expect(
|
||||
type.validate({
|
||||
foo: {
|
||||
bar: 'bar',
|
||||
baz: 'baz',
|
||||
},
|
||||
})
|
||||
).toEqual({
|
||||
foo: {
|
||||
bar: 'bar',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test('unknowns = `ignore` respects local preferences in sub-keys', () => {
|
||||
const type = schema.object(
|
||||
{ foo: schema.object({ bar: schema.string() }, { unknowns: 'forbid' }) },
|
||||
{ unknowns: 'ignore' }
|
||||
);
|
||||
|
||||
expect(() =>
|
||||
type.validate({
|
||||
foo: {
|
||||
|
@ -354,7 +374,7 @@ test('unknowns = `ignore` affects only own keys', () => {
|
|||
).toThrowErrorMatchingInlineSnapshot(`"[foo.baz]: definition for this key is missing"`);
|
||||
});
|
||||
|
||||
describe('nested unknows', () => {
|
||||
describe('nested unknowns', () => {
|
||||
test('allow unknown keys when unknowns = `allow`', () => {
|
||||
const type = schema.object({
|
||||
myObj: schema.object({ foo: schema.string({ defaultValue: 'test' }) }, { unknowns: 'allow' }),
|
||||
|
@ -427,8 +447,7 @@ describe('nested unknows', () => {
|
|||
},
|
||||
});
|
||||
});
|
||||
|
||||
test('unknowns = `ignore` affects only own keys', () => {
|
||||
test('unknowns = `ignore` is recursive if no explicit preferences in sub-keys', () => {
|
||||
const type = schema.object({
|
||||
myObj: schema.object(
|
||||
{ foo: schema.object({ bar: schema.string() }) },
|
||||
|
@ -436,6 +455,32 @@ describe('nested unknows', () => {
|
|||
),
|
||||
});
|
||||
|
||||
expect(
|
||||
type.validate({
|
||||
myObj: {
|
||||
foo: {
|
||||
bar: 'bar',
|
||||
baz: 'baz',
|
||||
},
|
||||
},
|
||||
})
|
||||
).toEqual({
|
||||
myObj: {
|
||||
foo: {
|
||||
bar: 'bar',
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test('unknowns = `ignore` respects local preferences in sub-keys', () => {
|
||||
const type = schema.object({
|
||||
myObj: schema.object(
|
||||
{ foo: schema.object({ bar: schema.string() }, { unknowns: 'forbid' }) },
|
||||
{ unknowns: 'ignore' }
|
||||
),
|
||||
});
|
||||
|
||||
expect(() =>
|
||||
type.validate({
|
||||
myObj: {
|
||||
|
|
|
@ -87,16 +87,11 @@ export class ObjectType<P extends Props = any> extends Type<ObjectResultType<P>>
|
|||
|
||||
constructor(props: P, options: ObjectTypeOptions<P> = {}) {
|
||||
const schemaKeys = {} as Record<string, AnySchema>;
|
||||
const { unknowns = 'forbid', ...typeOptions } = options;
|
||||
const { unknowns, ...typeOptions } = options;
|
||||
for (const [key, value] of Object.entries(props)) {
|
||||
schemaKeys[key] = value.getSchema();
|
||||
}
|
||||
let schema = internals
|
||||
.object()
|
||||
.keys(schemaKeys)
|
||||
.default()
|
||||
.optional()
|
||||
.options({ stripUnknown: { objects: unknowns === 'ignore' } });
|
||||
let schema = internals.object().keys(schemaKeys).default().optional();
|
||||
|
||||
// We need to specify the `.unknown` property only when we want to override the default `forbid`
|
||||
// or it will break `stripUnknown` functionality.
|
||||
|
@ -104,6 +99,11 @@ export class ObjectType<P extends Props = any> extends Type<ObjectResultType<P>>
|
|||
schema = schema.unknown(unknowns === 'allow');
|
||||
}
|
||||
|
||||
// Only set stripUnknown if we have an explicit value of `unknowns`
|
||||
if (unknowns) {
|
||||
schema = schema.options({ stripUnknown: { objects: unknowns === 'ignore' } });
|
||||
}
|
||||
|
||||
if (options.meta?.id) {
|
||||
schema = schema.id(options.meta.id);
|
||||
}
|
||||
|
|
|
@ -37,6 +37,16 @@ export interface SchemaStructureEntry {
|
|||
type: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Global validation Options to be provided when calling the `schema.validate()` method.
|
||||
*/
|
||||
export interface SchemaValidationOptions {
|
||||
/**
|
||||
* Remove unknown config keys
|
||||
*/
|
||||
stripUnknownKeys?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for dealing with unknown keys:
|
||||
* - allow: unknown keys will be permitted
|
||||
|
@ -129,10 +139,16 @@ export abstract class Type<V> {
|
|||
* Validates the provided value against this schema.
|
||||
* If valid, the resulting output will be returned, otherwise an exception will be thrown.
|
||||
*/
|
||||
public validate(value: unknown, context: Record<string, unknown> = {}, namespace?: string): V {
|
||||
public validate(
|
||||
value: unknown,
|
||||
context: Record<string, unknown> = {},
|
||||
namespace?: string,
|
||||
validationOptions?: SchemaValidationOptions
|
||||
): V {
|
||||
const { value: validatedValue, error } = this.internalSchema.validate(value, {
|
||||
context,
|
||||
presence: 'required',
|
||||
stripUnknown: { objects: validationOptions?.stripUnknownKeys === true },
|
||||
});
|
||||
|
||||
if (error) {
|
||||
|
|
|
@ -47,6 +47,7 @@ export class ConfigService {
|
|||
private readonly deprecationLog: Logger;
|
||||
private readonly docLinks: DocLinks;
|
||||
|
||||
private stripUnknownKeys = false;
|
||||
private validated = false;
|
||||
private readonly config$: Observable<Config>;
|
||||
private lastConfig?: Config;
|
||||
|
@ -96,6 +97,14 @@ export class ConfigService {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the global setting for stripUnknownKeys. Useful for running in Serverless-compatible way.
|
||||
* @param stripUnknownKeys Set to `true` if unknown keys (not explicitly forbidden) should be dropped without failing validation
|
||||
*/
|
||||
public setGlobalStripUnknownKeys(stripUnknownKeys: boolean) {
|
||||
this.stripUnknownKeys = stripUnknownKeys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set config schema for a path and performs its validation
|
||||
*/
|
||||
|
@ -139,7 +148,7 @@ export class ConfigService {
|
|||
public async validate(params: ConfigValidateParameters = { logDeprecations: true }) {
|
||||
const namespaces = [...this.schemas.keys()];
|
||||
for (let i = 0; i < namespaces.length; i++) {
|
||||
await this.getValidatedConfigAtPath$(namespaces[i]).pipe(first()).toPromise();
|
||||
await firstValueFrom(this.getValidatedConfigAtPath$(namespaces[i]));
|
||||
}
|
||||
|
||||
if (params.logDeprecations) {
|
||||
|
@ -313,7 +322,8 @@ export class ConfigService {
|
|||
serverless: this.env.packageInfo.buildFlavor === 'serverless',
|
||||
...this.env.packageInfo,
|
||||
},
|
||||
`config validation of [${namespace}]`
|
||||
`config validation of [${namespace}]`,
|
||||
this.stripUnknownKeys ? { stripUnknownKeys: this.stripUnknownKeys } : {}
|
||||
);
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -183,11 +183,6 @@ Object {
|
|||
"type": "string",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
|
@ -457,11 +452,6 @@ Object {
|
|||
"type": "string",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
],
|
||||
|
@ -814,11 +804,6 @@ Object {
|
|||
"type": "string",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"rules": Array [
|
||||
Object {
|
||||
"args": Object {
|
||||
|
@ -1129,11 +1114,6 @@ Object {
|
|||
"type": "any",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
}
|
||||
`;
|
||||
|
@ -1556,11 +1536,6 @@ Object {
|
|||
"type": "string",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"rules": Array [
|
||||
Object {
|
||||
"args": Object {
|
||||
|
@ -1784,11 +1759,6 @@ Object {
|
|||
"type": "string",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
}
|
||||
`;
|
||||
|
@ -1968,11 +1938,6 @@ Object {
|
|||
"type": "alternatives",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
|
@ -1981,11 +1946,6 @@ Object {
|
|||
"x-oas-optional": true,
|
||||
},
|
||||
],
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
"serviceName": Object {
|
||||
|
@ -2049,11 +2009,6 @@ Object {
|
|||
"type": "string",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
}
|
||||
`;
|
||||
|
@ -2256,11 +2211,6 @@ Object {
|
|||
"type": "alternatives",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
|
@ -2269,11 +2219,6 @@ Object {
|
|||
"x-oas-optional": true,
|
||||
},
|
||||
],
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
"serviceName": Object {
|
||||
|
@ -2379,11 +2324,6 @@ Object {
|
|||
"type": "string",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
}
|
||||
`;
|
||||
|
@ -2542,11 +2482,6 @@ Object {
|
|||
"type": "alternatives",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
|
@ -2555,11 +2490,6 @@ Object {
|
|||
"x-oas-optional": true,
|
||||
},
|
||||
],
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
"serviceName": Object {
|
||||
|
@ -2665,11 +2595,6 @@ Object {
|
|||
"type": "string",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
}
|
||||
`;
|
||||
|
@ -2824,11 +2749,6 @@ Object {
|
|||
"x-oas-optional": true,
|
||||
},
|
||||
],
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
"metric": Object {
|
||||
|
@ -2936,11 +2856,6 @@ Object {
|
|||
"type": "array",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
],
|
||||
|
@ -3225,11 +3140,6 @@ Object {
|
|||
"type": "string",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
|
@ -3302,11 +3212,6 @@ Object {
|
|||
"type": "string",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
|
@ -3352,11 +3257,6 @@ Object {
|
|||
"type": "string",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
],
|
||||
|
@ -3535,11 +3435,6 @@ Object {
|
|||
"type": "record",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
],
|
||||
|
@ -3712,11 +3607,6 @@ Object {
|
|||
"type": "string",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
|
@ -3803,11 +3693,6 @@ Object {
|
|||
"type": "any",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
|
@ -4021,11 +3906,6 @@ Object {
|
|||
"x-oas-optional": true,
|
||||
},
|
||||
],
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
"name": Object {
|
||||
|
@ -4184,11 +4064,6 @@ Object {
|
|||
"x-oas-optional": true,
|
||||
},
|
||||
],
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
"popularity": Object {
|
||||
|
@ -4239,11 +4114,6 @@ Object {
|
|||
"x-oas-optional": true,
|
||||
},
|
||||
],
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
"type": Object {
|
||||
|
@ -4339,11 +4209,6 @@ Object {
|
|||
"type": "alternatives",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
|
@ -4498,11 +4363,6 @@ Object {
|
|||
"x-oas-optional": true,
|
||||
},
|
||||
],
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
"popularity": Object {
|
||||
|
@ -4619,11 +4479,6 @@ Object {
|
|||
"type": "alternatives",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
|
@ -4659,11 +4514,6 @@ Object {
|
|||
"x-oas-optional": true,
|
||||
},
|
||||
],
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
"type": Object {
|
||||
|
@ -4677,11 +4527,6 @@ Object {
|
|||
"type": "any",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
|
@ -4796,11 +4641,6 @@ Object {
|
|||
"x-oas-optional": true,
|
||||
},
|
||||
],
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
"nested": Object {
|
||||
|
@ -4830,11 +4670,6 @@ Object {
|
|||
"x-oas-optional": true,
|
||||
},
|
||||
],
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
|
@ -4843,11 +4678,6 @@ Object {
|
|||
"x-oas-optional": true,
|
||||
},
|
||||
],
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
"type": Object {
|
||||
|
@ -5110,11 +4940,6 @@ Object {
|
|||
"x-oas-optional": true,
|
||||
},
|
||||
],
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
"popularity": Object {
|
||||
|
@ -5165,11 +4990,6 @@ Object {
|
|||
"x-oas-optional": true,
|
||||
},
|
||||
],
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
"type": Object {
|
||||
|
@ -5265,11 +5085,6 @@ Object {
|
|||
"type": "alternatives",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
|
@ -5424,11 +5239,6 @@ Object {
|
|||
"x-oas-optional": true,
|
||||
},
|
||||
],
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
"popularity": Object {
|
||||
|
@ -5545,11 +5355,6 @@ Object {
|
|||
"type": "alternatives",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
|
@ -5585,11 +5390,6 @@ Object {
|
|||
"x-oas-optional": true,
|
||||
},
|
||||
],
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
"type": Object {
|
||||
|
@ -5603,11 +5403,6 @@ Object {
|
|||
"type": "any",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
|
@ -5690,11 +5485,6 @@ Object {
|
|||
"type": "string",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
],
|
||||
|
@ -5803,11 +5593,6 @@ Object {
|
|||
"type": "string",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
|
@ -5858,19 +5643,9 @@ Object {
|
|||
"type": "string",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
|
@ -7909,11 +7684,6 @@ Object {
|
|||
"type": "string",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
}
|
||||
`;
|
||||
|
@ -9928,11 +9698,6 @@ Object {
|
|||
"type": "string",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
],
|
||||
|
@ -10035,11 +9800,6 @@ Object {
|
|||
"type": "number",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
"maxBurnRateThreshold": Object {
|
||||
|
@ -10102,30 +9862,15 @@ Object {
|
|||
"type": "number",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
],
|
||||
"type": "array",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
}
|
||||
`;
|
||||
|
@ -10255,11 +10000,6 @@ Object {
|
|||
"type": "boolean",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
|
@ -10304,11 +10044,6 @@ Object {
|
|||
"type": "boolean",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
|
@ -10353,11 +10088,6 @@ Object {
|
|||
"type": "boolean",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
|
@ -10377,11 +10107,6 @@ Object {
|
|||
"type": "alternatives",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
|
@ -10401,11 +10126,6 @@ Object {
|
|||
"type": "alternatives",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
}
|
||||
`;
|
||||
|
@ -10488,11 +10208,6 @@ Object {
|
|||
"type": "array",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"rules": Array [
|
||||
Object {
|
||||
"args": Object {
|
||||
|
@ -10644,11 +10359,6 @@ Object {
|
|||
"type": "alternatives",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
}
|
||||
`;
|
||||
|
@ -10731,11 +10441,6 @@ Object {
|
|||
"type": "array",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"rules": Array [
|
||||
Object {
|
||||
"args": Object {
|
||||
|
@ -10822,11 +10527,6 @@ Object {
|
|||
"type": "array",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"rules": Array [
|
||||
Object {
|
||||
"args": Object {
|
||||
|
@ -10918,11 +10618,6 @@ Object {
|
|||
"type": "alternatives",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
|
@ -10967,11 +10662,6 @@ Object {
|
|||
"type": "boolean",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
|
@ -11092,11 +10782,6 @@ Object {
|
|||
"type": "alternatives",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
|
@ -11141,11 +10826,6 @@ Object {
|
|||
"type": "boolean",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
|
@ -11190,11 +10870,6 @@ Object {
|
|||
"type": "boolean",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
|
@ -11214,11 +10889,6 @@ Object {
|
|||
"type": "alternatives",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
|
@ -11238,11 +10908,6 @@ Object {
|
|||
"type": "alternatives",
|
||||
},
|
||||
},
|
||||
"preferences": Object {
|
||||
"stripUnknown": Object {
|
||||
"objects": false,
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
}
|
||||
`;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue