[config-schema] offeringBasedSchema helper (#163786)

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Alejandro Fernández Haro 2023-08-22 12:59:15 +02:00 committed by GitHub
parent be32a39555
commit e98b4b3e88
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
39 changed files with 469 additions and 286 deletions

View file

@ -212,3 +212,22 @@ export const config = {
}),
};
----
For Serverless vs. Traditional configuration, you are encouraged to use the `offeringBasedSchema` helper:
[source,js]
----
import { schema, offeringBasedSchema } from '@kbn/config-schema'
export const config = {
schema: schema.object({
// Enabled by default in Dev mode
enabled: schema.boolean({ defaultValue: schema.contextRef('dev') }),
// Setting only allowed in the Serverless offering
plansForWorldPeace: offeringBasedSchema({
serverless: schema.string({ defaultValue: 'Free hugs' }),
}),
}),
};
----

View file

@ -6,7 +6,7 @@
* Side Public License, v 1.
*/
import { ByteSizeValue, schema, TypeOf } from '@kbn/config-schema';
import { ByteSizeValue, offeringBasedSchema, schema, TypeOf } from '@kbn/config-schema';
import { IHttpConfig, SslConfig, sslSchema } from '@kbn/server-http-tools';
import type { ServiceConfigDescriptor } from '@kbn/core-base-server-internal';
import { uuidRegexp } from '@kbn/core-base-server-internal';
@ -168,12 +168,9 @@ const configSchema = schema.object(
}
),
// allow access to internal routes by default to prevent breaking changes in current offerings
restrictInternalApis: schema.conditional(
schema.contextRef('serverless'),
true,
schema.boolean({ defaultValue: false }),
schema.never()
),
restrictInternalApis: offeringBasedSchema({
serverless: schema.boolean({ defaultValue: false }),
}),
versioned: schema.object({
/**

View file

@ -6,7 +6,7 @@
* Side Public License, v 1.
*/
import { schema, TypeOf } from '@kbn/config-schema';
import { schema, TypeOf, offeringBasedSchema } from '@kbn/config-schema';
import type { ServiceConfigDescriptor } from '@kbn/core-base-server-internal';
import { ConfigDeprecationProvider } from '@kbn/config';
@ -17,12 +17,7 @@ const deprecations: ConfigDeprecationProvider = ({ unused, renameFromRoot }) =>
const configSchema = schema.object({
overrides: schema.object({}, { unknowns: 'allow' }),
publicApiEnabled: schema.conditional(
schema.contextRef('serverless'),
true,
schema.boolean({ defaultValue: false }),
schema.never()
),
publicApiEnabled: offeringBasedSchema({ serverless: schema.boolean({ defaultValue: false }) }),
});
export type UiSettingsConfigType = TypeOf<typeof configSchema>;

View file

@ -55,6 +55,7 @@ export { ObjectType, Type };
export { ByteSizeValue } from './src/byte_size_value';
export { SchemaTypeError, ValidationError } from './src/errors';
export { isConfigSchema } from './src/typeguards';
export { offeringBasedSchema } from './src/helpers';
function any(options?: TypeOptions<any>) {
return new AnyType(options);

View file

@ -0,0 +1,9 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
export { offeringBasedSchema } from './offering_based_schema';

View file

@ -0,0 +1,216 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { schema } from '../..';
import { offeringBasedSchema } from './offering_based_schema';
describe('Helper: offeringBasedSchema()', () => {
describe('Example: Only allow the setting on Serverless', () => {
const validation = schema.object({
myProp: offeringBasedSchema({ serverless: schema.boolean({ defaultValue: true }) }),
});
test('it uses the non-serverless validation when the context is not present', () => {
expect(validation.validate({})).toEqual({});
});
test('it uses the non-serverless validation when context claims "not in serverless"', () => {
expect(validation.validate({}, { serverless: false })).toEqual({});
});
test('it uses serverless validation when context claims "in serverless"', () => {
expect(validation.validate({}, { serverless: true })).toEqual({ myProp: true });
});
test('it does not allow changing the flag when context claims "not in serverless"', () => {
expect(() =>
validation.validate({ myProp: true }, { serverless: false })
).toThrowErrorMatchingInlineSnapshot(`"[myProp]: a value wasn't expected to be present"`);
});
test('it allows changing the flag when context claims "in serverless"', () => {
expect(validation.validate({ myProp: false }, { serverless: true })).toEqual({
myProp: false,
});
});
});
describe('Example: Only allow the setting on Traditional', () => {
const validation = schema.object({
myProp: offeringBasedSchema({ traditional: schema.boolean({ defaultValue: true }) }),
});
test('it uses the non-serverless validation when the context is not present', () => {
expect(validation.validate({})).toEqual({ myProp: true });
});
test('it uses the non-serverless validation when context claims "not in serverless"', () => {
expect(validation.validate({}, { serverless: false })).toEqual({ myProp: true });
});
test('it uses serverless validation when context claims "in serverless"', () => {
expect(validation.validate({}, { serverless: true })).toEqual({});
});
test('it allows changing the flag when context claims "not in serverless"', () => {
expect(validation.validate({ myProp: false }, { serverless: false })).toEqual({
myProp: false,
});
});
test('it does not allow changing the flag when context claims "in serverless"', () => {
expect(() =>
validation.validate({ myProp: true }, { serverless: true })
).toThrowErrorMatchingInlineSnapshot(`"[myProp]: a value wasn't expected to be present"`);
});
});
describe('Example: Fixed setting on Traditional, configurable on Serverless', () => {
const validation = schema.object({
myProp: offeringBasedSchema({
serverless: schema.boolean({ defaultValue: true }),
options: { defaultValue: false },
}),
});
test('it uses the non-serverless validation when the context is not present', () => {
expect(validation.validate({})).toEqual({ myProp: false });
});
test('it uses the non-serverless validation when context claims "not in serverless"', () => {
expect(validation.validate({}, { serverless: false })).toEqual({ myProp: false });
});
test('it uses serverless validation when context claims "in serverless"', () => {
expect(validation.validate({}, { serverless: true })).toEqual({ myProp: true });
});
test('it does not allow changing the flag when context claims "not in serverless"', () => {
expect(() =>
validation.validate({ myProp: true }, { serverless: false })
).toThrowErrorMatchingInlineSnapshot(`"[myProp]: a value wasn't expected to be present"`);
});
test('it allows changing the flag when context claims "in serverless"', () => {
expect(validation.validate({ myProp: false }, { serverless: true })).toEqual({
myProp: false,
});
});
});
describe('Example: Fixed setting on Traditional (though settable), configurable on Serverless', () => {
const validation = schema.object({
myProp: offeringBasedSchema({
serverless: schema.boolean({ defaultValue: true }),
traditional: schema.literal(false),
options: { defaultValue: false },
}),
});
test('it uses the non-serverless validation when the context is not present', () => {
expect(validation.validate({})).toEqual({ myProp: false });
});
test('it uses the non-serverless validation when context claims "not in serverless"', () => {
expect(validation.validate({}, { serverless: false })).toEqual({ myProp: false });
});
test('it uses serverless validation when context claims "in serverless"', () => {
expect(validation.validate({}, { serverless: true })).toEqual({ myProp: true });
});
test('it does not allow changing the flag when context claims "not in serverless"', () => {
expect(() =>
validation.validate({ myProp: true }, { serverless: false })
).toThrowErrorMatchingInlineSnapshot(`"[myProp]: expected value to equal [false]"`);
});
test('it allows changing the flag when context claims "in serverless"', () => {
expect(validation.validate({ myProp: false }, { serverless: true })).toEqual({
myProp: false,
});
});
});
describe('Example: Fixed setting on Serverless (though settable), configurable on Traditional', () => {
const validation = schema.object({
myProp: offeringBasedSchema({
serverless: schema.literal(false),
traditional: schema.boolean({ defaultValue: true }),
options: { defaultValue: false },
}),
});
test('it uses the non-serverless validation when the context is not present', () => {
expect(validation.validate({})).toEqual({ myProp: true });
});
test('it uses the non-serverless validation when context claims "not in serverless"', () => {
expect(validation.validate({}, { serverless: false })).toEqual({ myProp: true });
});
test('it uses serverless validation when context claims "in serverless"', () => {
expect(validation.validate({}, { serverless: true })).toEqual({ myProp: false });
});
test('it allows changing the flag when context claims "not in serverless"', () => {
expect(validation.validate({ myProp: false }, { serverless: false })).toEqual({
myProp: false,
});
});
test('it does not allow changing the flag when context claims "in serverless"', () => {
expect(() =>
validation.validate({ myProp: true }, { serverless: true })
).toThrowErrorMatchingInlineSnapshot(`"[myProp]: expected value to equal [false]"`);
});
});
describe('Example: Setting is changeable on all offerings but with different defaults', () => {
const validation = schema.object({
myProp: offeringBasedSchema({
serverless: schema.boolean({ defaultValue: true }),
traditional: schema.boolean({ defaultValue: false }),
}),
});
test('it uses the non-serverless validation when the context is not present', () => {
expect(validation.validate({})).toEqual({ myProp: false });
});
test('it uses the non-serverless validation when context claims "not in serverless"', () => {
expect(validation.validate({}, { serverless: false })).toEqual({ myProp: false });
});
test('it uses serverless validation when context claims "in serverless"', () => {
expect(validation.validate({}, { serverless: true })).toEqual({ myProp: true });
});
test('it allows changing the flag when context claims "not in serverless"', () => {
expect(validation.validate({ myProp: true }, { serverless: false })).toEqual({
myProp: true,
});
});
test('it allows changing the flag when context claims "in serverless"', () => {
expect(validation.validate({ myProp: false }, { serverless: true })).toEqual({
myProp: false,
});
});
});
test('TS enforces the same types on both entries', () => {
schema.object({
myProp: offeringBasedSchema({
serverless: schema.boolean({ defaultValue: true }),
// @ts-expect-error
traditional: schema.string({ defaultValue: 'not on serverless' }),
}),
});
});
});

View file

@ -0,0 +1,59 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { schema } from '../..';
import { Type, TypeOptions } from '../types';
/**
* Helper to apply different validations depending on whether Kibana is running the Serverless or Traditional offering.
*
* @example Only allow the setting on Serverless
* const config = schema.object({
* myProp: offeringBasedSchema({ serverless: schema.boolean({ defaultValue: true }) }),
* });
*
* @example Only allow the setting on Traditional
* const config = schema.object({
* myProp: offeringBasedSchema({ fullyManaged: schema.boolean({ defaultValue: true }) }),
* });
*
* @example Fixed value on Traditional, configurable on Serverless
* const config = schema.object({
* myProp: offeringBasedSchema({
* serverless: schema.boolean({ defaultValue: true }),
* traditional: schema.literal(false), // this can be skipped if users can't specify it in the config
* options: { defaultValue: false },
* }),
* });
*
* @example Setting is changeable on all offerings but with different defaults
* const config = schema.object({
* myProp: offeringBasedSchema({
* serverless: schema.boolean({ defaultValue: true }),
* traditional: schema.boolean({ defaultValue: false }),
* }),
* });
*
* @param opts.serverless The validation to apply in the Serverless offering. If not provided, it doesn't allow the setting to be set in this offering.
* @param opts.traditional The validation to apply in the Traditional offering. If not provided, it doesn't allow the setting to be set in this offering.
* @param opts.options Any options to pass down in the types.
*/
export function offeringBasedSchema<V>(opts: {
serverless?: Type<V>;
traditional?: Type<V>;
options?: TypeOptions<V>;
}) {
const { serverless = schema.never(), traditional = schema.never(), options } = opts;
return schema.conditional(
schema.contextRef('serverless'),
true,
serverless,
traditional,
options
);
}

View file

@ -6,15 +6,12 @@
* Side Public License, v 1.
*/
import { schema, TypeOf } from '@kbn/config-schema';
import { schema, TypeOf, offeringBasedSchema } from '@kbn/config-schema';
export const configSchema = schema.object({
readOnly: schema.conditional(
schema.contextRef('serverless'),
true,
schema.maybe(schema.boolean({ defaultValue: false })),
schema.never()
),
readOnly: offeringBasedSchema({
serverless: schema.boolean({ defaultValue: false }),
}),
});
export type InputControlConfig = TypeOf<typeof configSchema>;

View file

@ -6,7 +6,7 @@
* Side Public License, v 1.
*/
import { schema, TypeOf, Type } from '@kbn/config-schema';
import { schema, TypeOf, Type, offeringBasedSchema } from '@kbn/config-schema';
import { getConfigPath } from '@kbn/utils';
import { PluginConfigDescriptor } from '@kbn/core/server';
import { labelsSchema } from './telemetry_labels';
@ -33,13 +33,11 @@ const configSchema = schema.object({
sendUsageFrom: schema.oneOf([schema.literal('server'), schema.literal('browser')], {
defaultValue: 'server',
}),
appendServerlessChannelsSuffix: schema.conditional(
schema.contextRef('serverless'),
true,
schema.literal(true),
schema.literal(false),
{ defaultValue: schema.contextRef('serverless') }
),
appendServerlessChannelsSuffix: offeringBasedSchema({
serverless: schema.literal(true),
traditional: schema.literal(false),
options: { defaultValue: schema.contextRef('serverless') },
}),
// Used for extra enrichment of telemetry
labels: labelsSchema,
});

View file

@ -6,7 +6,7 @@
* Side Public License, v 1.
*/
import { schema, TypeOf } from '@kbn/config-schema';
import { offeringBasedSchema, schema, TypeOf } from '@kbn/config-schema';
/**
* Labels to enrich the context of the telemetry generated.
@ -31,9 +31,7 @@ export const labelsSchema = schema.object(
* The serverless project type.
* Flagging it as maybe because these settings should never affect how Kibana runs.
*/
serverless: schema.maybe(
schema.conditional(schema.contextRef('serverless'), true, schema.string(), schema.never())
),
serverless: offeringBasedSchema({ serverless: schema.maybe(schema.string()) }),
},
{ defaultValue: {} }
);

View file

@ -6,17 +6,14 @@
* Side Public License, v 1.
*/
import { schema, TypeOf } from '@kbn/config-schema';
import { offeringBasedSchema, schema, TypeOf } from '@kbn/config-schema';
export const configSchema = schema.object({
enabled: schema.boolean({ defaultValue: true }),
readOnly: schema.conditional(
schema.contextRef('serverless'),
true,
schema.maybe(schema.boolean({ defaultValue: false })),
schema.never()
),
readOnly: offeringBasedSchema({
serverless: schema.boolean({ defaultValue: false }),
}),
});
export type GaugeConfig = TypeOf<typeof configSchema>;

View file

@ -6,17 +6,14 @@
* Side Public License, v 1.
*/
import { schema, TypeOf } from '@kbn/config-schema';
import { offeringBasedSchema, schema, TypeOf } from '@kbn/config-schema';
export const configSchema = schema.object({
enabled: schema.boolean({ defaultValue: true }),
readOnly: schema.conditional(
schema.contextRef('serverless'),
true,
schema.maybe(schema.boolean({ defaultValue: false })),
schema.never()
),
readOnly: offeringBasedSchema({
serverless: schema.boolean({ defaultValue: false }),
}),
});
export type HeatmapConfig = TypeOf<typeof configSchema>;

View file

@ -6,17 +6,14 @@
* Side Public License, v 1.
*/
import { schema, TypeOf } from '@kbn/config-schema';
import { offeringBasedSchema, schema, TypeOf } from '@kbn/config-schema';
export const configSchema = schema.object({
enabled: schema.boolean({ defaultValue: true }),
readOnly: schema.conditional(
schema.contextRef('serverless'),
true,
schema.maybe(schema.boolean({ defaultValue: false })),
schema.never()
),
readOnly: offeringBasedSchema({
serverless: schema.boolean({ defaultValue: false }),
}),
});
export type MetricConfig = TypeOf<typeof configSchema>;

View file

@ -6,17 +6,14 @@
* Side Public License, v 1.
*/
import { schema, TypeOf } from '@kbn/config-schema';
import { offeringBasedSchema, schema, TypeOf } from '@kbn/config-schema';
export const configSchema = schema.object({
enabled: schema.boolean({ defaultValue: true }),
readOnly: schema.conditional(
schema.contextRef('serverless'),
true,
schema.maybe(schema.boolean({ defaultValue: false })),
schema.never()
),
readOnly: offeringBasedSchema({
serverless: schema.boolean({ defaultValue: false }),
}),
});
export type PieConfig = TypeOf<typeof configSchema>;

View file

@ -6,17 +6,14 @@
* Side Public License, v 1.
*/
import { schema, TypeOf } from '@kbn/config-schema';
import { offeringBasedSchema, schema, TypeOf } from '@kbn/config-schema';
export const configSchema = schema.object({
enabled: schema.boolean({ defaultValue: true }),
readOnly: schema.conditional(
schema.contextRef('serverless'),
true,
schema.maybe(schema.boolean({ defaultValue: false })),
schema.never()
),
readOnly: offeringBasedSchema({
serverless: schema.boolean({ defaultValue: false }),
}),
});
export type TableConfig = TypeOf<typeof configSchema>;

View file

@ -6,17 +6,14 @@
* Side Public License, v 1.
*/
import { schema, TypeOf } from '@kbn/config-schema';
import { offeringBasedSchema, schema, TypeOf } from '@kbn/config-schema';
export const configSchema = schema.object({
enabled: schema.boolean({ defaultValue: true }),
readOnly: schema.conditional(
schema.contextRef('serverless'),
true,
schema.maybe(schema.boolean({ defaultValue: false })),
schema.never()
),
readOnly: offeringBasedSchema({
serverless: schema.boolean({ defaultValue: false }),
}),
});
export type TagcloudConfig = TypeOf<typeof configSchema>;

View file

@ -6,18 +6,15 @@
* Side Public License, v 1.
*/
import { schema, TypeOf } from '@kbn/config-schema';
import { offeringBasedSchema, schema, TypeOf } from '@kbn/config-schema';
export const configSchema = schema.object({
graphiteUrls: schema.maybe(schema.arrayOf(schema.string())),
enabled: schema.boolean({ defaultValue: true }),
readOnly: schema.conditional(
schema.contextRef('serverless'),
true,
schema.maybe(schema.boolean({ defaultValue: false })),
schema.never()
),
readOnly: offeringBasedSchema({
serverless: schema.boolean({ defaultValue: false }),
}),
});
export type TimelionConfig = TypeOf<typeof configSchema>;

View file

@ -6,17 +6,14 @@
* Side Public License, v 1.
*/
import { schema, TypeOf } from '@kbn/config-schema';
import { offeringBasedSchema, schema, TypeOf } from '@kbn/config-schema';
export const config = schema.object({
enabled: schema.boolean({ defaultValue: true }),
readOnly: schema.conditional(
schema.contextRef('serverless'),
true,
schema.maybe(schema.boolean({ defaultValue: false })),
schema.never()
),
readOnly: offeringBasedSchema({
serverless: schema.boolean({ defaultValue: false }),
}),
/** @deprecated **/
chartResolution: schema.number({ defaultValue: 150 }),

View file

@ -6,17 +6,14 @@
* Side Public License, v 1.
*/
import { schema, TypeOf } from '@kbn/config-schema';
import { offeringBasedSchema, schema, TypeOf } from '@kbn/config-schema';
export const configSchema = schema.object({
enabled: schema.boolean({ defaultValue: true }),
readOnly: schema.conditional(
schema.contextRef('serverless'),
true,
schema.maybe(schema.boolean({ defaultValue: false })),
schema.never()
),
readOnly: offeringBasedSchema({
serverless: schema.boolean({ defaultValue: false }),
}),
});
export type VislibConfig = TypeOf<typeof configSchema>;

View file

@ -6,17 +6,14 @@
* Side Public License, v 1.
*/
import { schema, TypeOf } from '@kbn/config-schema';
import { offeringBasedSchema, schema, TypeOf } from '@kbn/config-schema';
export const configSchema = schema.object({
enabled: schema.boolean({ defaultValue: true }),
readOnly: schema.conditional(
schema.contextRef('serverless'),
true,
schema.maybe(schema.boolean({ defaultValue: false })),
schema.never()
),
readOnly: offeringBasedSchema({
serverless: schema.boolean({ defaultValue: false }),
}),
});
export type XyConfig = TypeOf<typeof configSchema>;

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import { schema, TypeOf } from '@kbn/config-schema';
import { offeringBasedSchema, schema, TypeOf } from '@kbn/config-schema';
import {
PluginConfigDescriptor,
PluginInitializerContext,
@ -14,14 +14,12 @@ import { maxSuggestions } from '@kbn/observability-plugin/common';
import { SearchAggregatedTransactionSetting } from '../common/aggregated_transactions';
import { APMPlugin } from './plugin';
const disabledOnServerless = schema.conditional(
schema.contextRef('serverless'),
true,
schema.boolean({
const disabledOnServerless = offeringBasedSchema({
serverless: schema.boolean({
defaultValue: false,
}),
schema.oneOf([schema.literal(true)], { defaultValue: true })
);
traditional: schema.oneOf([schema.literal(true)], { defaultValue: true }),
});
// All options should be documented in the APM configuration settings: https://github.com/elastic/kibana/blob/main/docs/settings/apm-settings.asciidoc
// and be included on cloud allow list unless there are specific reasons not to
@ -61,18 +59,12 @@ const configSchema = schema.object({
defaultValue: 'https://apm-agent-versions.elastic.co/versions.json',
}),
enabled: schema.boolean({ defaultValue: true }),
serverlessOnboarding: schema.conditional(
schema.contextRef('serverless'),
true,
schema.boolean({ defaultValue: false }),
schema.never()
),
managedServiceUrl: schema.conditional(
schema.contextRef('serverless'),
true,
schema.string({ defaultValue: '' }),
schema.never()
),
serverlessOnboarding: offeringBasedSchema({
serverless: schema.boolean({ defaultValue: false }),
}),
managedServiceUrl: offeringBasedSchema({
serverless: schema.string({ defaultValue: '' }),
}),
featureFlags: schema.object({
agentConfigurationAvailable: disabledOnServerless,
configurableIndicesAvailable: disabledOnServerless,
@ -83,13 +75,10 @@ const configSchema = schema.object({
storageExplorerAvailable: disabledOnServerless,
}),
serverless: schema.object({
enabled: schema.conditional(
schema.contextRef('serverless'),
true,
schema.literal(true),
schema.never(),
{ defaultValue: schema.contextRef('serverless') }
),
enabled: offeringBasedSchema({
serverless: schema.literal(true),
options: { defaultValue: schema.contextRef('serverless') },
}),
}),
});

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import { schema, TypeOf } from '@kbn/config-schema';
import { offeringBasedSchema, schema, TypeOf } from '@kbn/config-schema';
import { PluginConfigDescriptor } from '@kbn/core/server';
const apmConfigSchema = schema.object({
@ -29,12 +29,7 @@ const configSchema = schema.object({
users_and_roles_url: schema.maybe(schema.string()),
organization_url: schema.maybe(schema.string()),
profile_url: schema.maybe(schema.string()),
projects_url: schema.conditional(
schema.contextRef('serverless'),
true,
schema.string({ defaultValue: '/projects/' }),
schema.never()
),
projects_url: offeringBasedSchema({ serverless: schema.string({ defaultValue: '/projects/' }) }),
trial_end_date: schema.maybe(schema.string()),
is_elastic_staff_owned: schema.maybe(schema.boolean()),
serverless: schema.maybe(

View file

@ -5,18 +5,15 @@
* 2.0.
*/
import { schema, TypeOf } from '@kbn/config-schema';
import { offeringBasedSchema, schema, TypeOf } from '@kbn/config-schema';
import { PluginConfigDescriptor } from '@kbn/core-plugins-server';
const configSchema = schema.object({
enabled: schema.conditional(
schema.contextRef('serverless'),
true,
enabled: offeringBasedSchema({
// cloud_data_migration is disabled in serverless; refer to the serverless.yml file as the source of truth
// We take this approach in order to have a central place (serverless.yml) to view disabled plugins across Kibana
schema.boolean({ defaultValue: true }),
schema.never()
),
serverless: schema.boolean({ defaultValue: true }),
}),
});
export type CloudDataMigrationConfig = TypeOf<typeof configSchema>;

View file

@ -7,7 +7,7 @@
import { SemVer } from 'semver';
import { i18n } from '@kbn/i18n';
import { get } from 'lodash';
import { schema, TypeOf } from '@kbn/config-schema';
import { offeringBasedSchema, schema, TypeOf } from '@kbn/config-schema';
import { PluginConfigDescriptor } from '@kbn/core/server';
import { MAJOR_VERSION } from '../common/constants';
@ -26,14 +26,11 @@ const schemaLatest = schema.object(
* Disables the plugin.
* Added back in 8.8.
*/
enabled: schema.conditional(
schema.contextRef('serverless'),
true,
enabled: offeringBasedSchema({
// CCR is disabled in serverless; refer to the serverless.yml file as the source of truth
// We take this approach in order to have a central place (serverless.yml) to view disabled plugins across Kibana
schema.boolean({ defaultValue: true }),
schema.never()
),
serverless: schema.boolean({ defaultValue: true }),
}),
},
{ defaultValue: undefined }
);

View file

@ -5,22 +5,19 @@
* 2.0.
*/
import { schema } from '@kbn/config-schema';
import { schema, offeringBasedSchema } from '@kbn/config-schema';
import { PluginConfigDescriptor } from '@kbn/core/server';
import { DiscoverLogExplorerConfig } from '../common/plugin_config';
export const configSchema = schema.object({
featureFlags: schema.object({
deepLinkVisible: schema.conditional(
schema.contextRef('serverless'),
true,
schema.boolean(),
schema.never(),
{
deepLinkVisible: offeringBasedSchema({
serverless: schema.boolean(),
options: {
defaultValue: false,
}
),
},
}),
}),
});

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import { schema, TypeOf } from '@kbn/config-schema';
import { schema, TypeOf, offeringBasedSchema } from '@kbn/config-schema';
export const configSchema = schema.object({
savePolicy: schema.oneOf(
@ -18,12 +18,7 @@ export const configSchema = schema.object({
{ defaultValue: 'configAndData' }
),
canEditDrillDownUrls: schema.boolean({ defaultValue: true }),
enabled: schema.conditional(
schema.contextRef('serverless'),
true,
schema.maybe(schema.boolean({ defaultValue: true })),
schema.never()
),
enabled: offeringBasedSchema({ serverless: schema.boolean({ defaultValue: true }) }),
});
export type ConfigSchema = TypeOf<typeof configSchema>;

View file

@ -7,7 +7,7 @@
import { SemVer } from 'semver';
import { i18n } from '@kbn/i18n';
import { get } from 'lodash';
import { schema, TypeOf } from '@kbn/config-schema';
import { offeringBasedSchema, schema, TypeOf } from '@kbn/config-schema';
import { PluginConfigDescriptor } from '@kbn/core/server';
import { MAJOR_VERSION } from '../common/constants';
@ -28,14 +28,11 @@ const schemaLatest = schema.object(
* Disables the plugin.
* Added back in 8.8.
*/
enabled: schema.conditional(
schema.contextRef('serverless'),
true,
enabled: offeringBasedSchema({
// ILM is disabled in serverless; refer to the serverless.yml file as the source of truth
// We take this approach in order to have a central place (serverless.yml) to view disabled plugins across Kibana
schema.boolean({ defaultValue: true }),
schema.never()
),
serverless: schema.boolean({ defaultValue: true }),
}),
},
{ defaultValue: undefined }
);

View file

@ -7,7 +7,7 @@
import { SemVer } from 'semver';
import { i18n } from '@kbn/i18n';
import { get } from 'lodash';
import { schema, TypeOf } from '@kbn/config-schema';
import { offeringBasedSchema, schema, TypeOf } from '@kbn/config-schema';
import { PluginConfigDescriptor } from '@kbn/core/server';
import { MAJOR_VERSION } from '../common/constants';
@ -22,22 +22,16 @@ const schemaLatest = schema.object(
ui: schema.object({
enabled: schema.boolean({ defaultValue: true }),
}),
enableIndexActions: schema.conditional(
schema.contextRef('serverless'),
true,
enableIndexActions: offeringBasedSchema({
// Index actions are disabled in serverless; refer to the serverless.yml file as the source of truth
// We take this approach in order to have a central place (serverless.yml) for serverless config across Kibana
schema.boolean({ defaultValue: true }),
schema.never()
),
enableLegacyTemplates: schema.conditional(
schema.contextRef('serverless'),
true,
serverless: schema.boolean({ defaultValue: true }),
}),
enableLegacyTemplates: offeringBasedSchema({
// Legacy templates functionality is disabled in serverless; refer to the serverless.yml file as the source of truth
// We take this approach in order to have a central place (serverless.yml) for serverless config across Kibana
schema.boolean({ defaultValue: true }),
schema.never()
),
serverless: schema.boolean({ defaultValue: true }),
}),
dev: schema.object({ enableIndexDetailsPage: schema.boolean({ defaultValue: false }) }),
},
{ defaultValue: undefined }

View file

@ -6,7 +6,7 @@
*/
import { Server } from '@hapi/hapi';
import { schema } from '@kbn/config-schema';
import { offeringBasedSchema, schema } from '@kbn/config-schema';
import {
CoreStart,
Plugin,
@ -62,20 +62,17 @@ export const config: PluginConfigDescriptor<InfraConfig> = {
schema: schema.object({
enabled: schema.boolean({ defaultValue: true }),
// Setting variants only allowed in the Serverless offering, otherwise always default `logs-ui` value
logs: schema.conditional(
schema.contextRef('serverless'),
true,
schema.object({
logs: offeringBasedSchema({
serverless: schema.object({
app_target: schema.oneOf(
[schema.literal(LOGS_APP_TARGET), schema.literal(DISCOVER_APP_TARGET)],
{ defaultValue: LOGS_APP_TARGET }
),
}),
schema.never(),
{
defaultValue: { app_target: LOGS_APP_TARGET },
}
),
options: {
defaultValue: { app_target: LOGS_APP_TARGET } as const, // "as const" is required for TS to not generalize `app_target: string`
},
}),
alerting: schema.object({
inventory_threshold: schema.object({
group_by_page_size: schema.number({ defaultValue: 5_000 }),

View file

@ -7,7 +7,7 @@
import { SemVer } from 'semver';
import { i18n } from '@kbn/i18n';
import { get } from 'lodash';
import { schema, TypeOf } from '@kbn/config-schema';
import { offeringBasedSchema, schema, TypeOf } from '@kbn/config-schema';
import { PluginConfigDescriptor } from '@kbn/core/server';
import { MAJOR_VERSION } from '../common/constants';
@ -26,14 +26,11 @@ const schemaLatest = schema.object(
* Disables the plugin.
* Added back in 8.8.
*/
enabled: schema.conditional(
schema.contextRef('serverless'),
true,
enabled: offeringBasedSchema({
// License Management is disabled in serverless; refer to the serverless.yml file as the source of truth
// We take this approach in order to have a central place (serverless.yml) to view disabled plugins across Kibana
schema.boolean({ defaultValue: true }),
schema.never()
),
serverless: schema.boolean({ defaultValue: true }),
}),
},
{ defaultValue: undefined }
);

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import { schema, TypeOf } from '@kbn/config-schema';
import { offeringBasedSchema, schema, TypeOf } from '@kbn/config-schema';
import {
PluginConfigDescriptor,
PluginInitializerContext,
@ -17,13 +17,10 @@ const configSchema = schema.object({
enabled: schema.boolean({ defaultValue: true }),
}),
serverless: schema.object({
enabled: schema.conditional(
schema.contextRef('serverless'),
true,
schema.literal(true),
schema.never(),
{ defaultValue: schema.contextRef('serverless') }
),
enabled: offeringBasedSchema({
serverless: schema.literal(true),
options: { defaultValue: schema.contextRef('serverless') },
}),
}),
});

View file

@ -7,7 +7,7 @@
import { SemVer } from 'semver';
import { i18n } from '@kbn/i18n';
import { get } from 'lodash';
import { schema, TypeOf } from '@kbn/config-schema';
import { offeringBasedSchema, schema, TypeOf } from '@kbn/config-schema';
import { PluginConfigDescriptor } from '@kbn/core/server';
import { MAJOR_VERSION } from '../common/constants';
@ -26,14 +26,11 @@ const schemaLatest = schema.object(
* Disables the plugin.
* Added back in 8.8.
*/
enabled: schema.conditional(
schema.contextRef('serverless'),
true,
enabled: offeringBasedSchema({
// Remote Clusters is disabled in serverless; refer to the serverless.yml file as the source of truth
// We take this approach in order to have a central place (serverless.yml) to view disabled plugins across Kibana
schema.boolean({ defaultValue: true }),
schema.never()
),
serverless: schema.boolean({ defaultValue: true }),
}),
},
{ defaultValue: undefined }
);

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import { ByteSizeValue, schema, TypeOf } from '@kbn/config-schema';
import { ByteSizeValue, offeringBasedSchema, schema, TypeOf } from '@kbn/config-schema';
import ipaddr from 'ipaddr.js';
import { sum } from 'lodash';
import moment from 'moment';
@ -84,18 +84,14 @@ const EncryptionKeySchema = schema.conditional(
);
const RolesSchema = schema.object({
enabled: schema.conditional(
schema.contextRef('serverless'),
true,
schema.boolean({ defaultValue: false }),
schema.boolean({ defaultValue: true })
), // true: use ES API for access control (deprecated in 7.x). false: use Kibana API for application features (8.0)
allow: schema.conditional(
schema.contextRef('serverless'),
true,
schema.arrayOf(schema.string(), { defaultValue: [] }),
schema.arrayOf(schema.string(), { defaultValue: ['reporting_user'] })
),
enabled: offeringBasedSchema({
serverless: schema.boolean({ defaultValue: false }),
traditional: schema.boolean({ defaultValue: true }),
}), // true: use ES API for access control (deprecated in 7.x). false: use Kibana API for application features (8.0)
allow: offeringBasedSchema({
serverless: schema.arrayOf(schema.string(), { defaultValue: [] }),
traditional: schema.arrayOf(schema.string(), { defaultValue: ['reporting_user'] }),
}),
});
// Browser side polling: job completion notifier, management table auto-refresh
@ -118,21 +114,17 @@ const ExportTypeSchema = schema.object({
}),
// Png reports are disabled in serverless
png: schema.object({
enabled: schema.conditional(
schema.contextRef('serverless'),
true,
schema.boolean({ defaultValue: false }),
schema.boolean({ defaultValue: true })
),
enabled: offeringBasedSchema({
serverless: schema.boolean({ defaultValue: false }),
traditional: schema.boolean({ defaultValue: true }),
}),
}),
// Pdf reports are disabled in serverless
pdf: schema.object({
enabled: schema.conditional(
schema.contextRef('serverless'),
true,
schema.boolean({ defaultValue: false }),
schema.boolean({ defaultValue: true })
),
enabled: offeringBasedSchema({
serverless: schema.boolean({ defaultValue: false }),
traditional: schema.boolean({ defaultValue: true }),
}),
}),
});

View file

@ -7,7 +7,7 @@
import { SemVer } from 'semver';
import { i18n } from '@kbn/i18n';
import { get } from 'lodash';
import { schema, TypeOf } from '@kbn/config-schema';
import { offeringBasedSchema, schema, TypeOf } from '@kbn/config-schema';
import { PluginConfigDescriptor } from '@kbn/core/server';
import { MAJOR_VERSION } from '../common';
@ -26,14 +26,11 @@ const schemaLatest = schema.object(
* Disables the plugin.
* Added back in 8.8.
*/
enabled: schema.conditional(
schema.contextRef('serverless'),
true,
enabled: offeringBasedSchema({
// Rollups is disabled in serverless; refer to the serverless.yml file as the source of truth
// We take this approach in order to have a central place (serverless.yml) to view disabled plugins across Kibana
schema.boolean({ defaultValue: true }),
schema.never()
),
serverless: schema.boolean({ defaultValue: true }),
}),
},
{ defaultValue: undefined }
);

View file

@ -10,7 +10,7 @@ import type { Duration } from 'moment';
import path from 'path';
import type { Type, TypeOf } from '@kbn/config-schema';
import { schema } from '@kbn/config-schema';
import { offeringBasedSchema, schema } from '@kbn/config-schema';
import type { AppenderConfigType, Logger } from '@kbn/core/server';
import { config as coreConfig } from '@kbn/core/server';
import { i18n } from '@kbn/i18n';
@ -299,16 +299,13 @@ export const ConfigSchema = schema.object({
enabled: schema.boolean({ defaultValue: true }),
// Setting only allowed in the Serverless offering
ui: schema.conditional(
schema.contextRef('serverless'),
true,
schema.object({
ui: offeringBasedSchema({
serverless: schema.object({
userManagementEnabled: schema.boolean({ defaultValue: true }),
roleManagementEnabled: schema.boolean({ defaultValue: true }),
roleMappingManagementEnabled: schema.boolean({ defaultValue: true }),
}),
schema.never()
),
}),
});
export function createConfig(

View file

@ -7,7 +7,7 @@
import { SemVer } from 'semver';
import { i18n } from '@kbn/i18n';
import { get } from 'lodash';
import { schema, TypeOf } from '@kbn/config-schema';
import { offeringBasedSchema, schema, TypeOf } from '@kbn/config-schema';
import { PluginConfigDescriptor } from '@kbn/core/server';
import { MAJOR_VERSION } from '../common/constants';
@ -29,14 +29,11 @@ const schemaLatest = schema.object(
* Disables the plugin.
* Added back in 8.8.
*/
enabled: schema.conditional(
schema.contextRef('serverless'),
true,
enabled: offeringBasedSchema({
// Snapshot & Restore is disabled in serverless; refer to the serverless.yml file as the source of truth
// We take this approach in order to have a central place (serverless.yml) to view disabled plugins across Kibana
schema.boolean({ defaultValue: true }),
schema.never()
),
serverless: schema.boolean({ defaultValue: true }),
}),
},
{ defaultValue: undefined }
);

View file

@ -8,7 +8,7 @@
import type { Observable } from 'rxjs';
import type { TypeOf } from '@kbn/config-schema';
import { schema } from '@kbn/config-schema';
import { offeringBasedSchema, schema } from '@kbn/config-schema';
import type { PluginInitializerContext } from '@kbn/core/server';
export const ConfigSchema = schema.object({
@ -26,11 +26,9 @@ export const ConfigSchema = schema.object({
})
),
maxSpaces: schema.number({ defaultValue: 1000 }),
allowFeatureVisibility: schema.conditional(
schema.contextRef('serverless'),
true,
schema.literal(false),
schema.boolean({
allowFeatureVisibility: offeringBasedSchema({
serverless: schema.literal(false),
traditional: schema.boolean({
validate: (rawValue) => {
// This setting should not be configurable on-prem to avoid bugs when e.g. existing spaces
// have feature visibility customized but admins would be unable to change them back if the
@ -40,8 +38,8 @@ export const ConfigSchema = schema.object({
}
},
defaultValue: true,
})
),
}),
}),
});
export function createConfig$(context: PluginInitializerContext) {

View file

@ -4,7 +4,7 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { schema, TypeOf } from '@kbn/config-schema';
import { offeringBasedSchema, schema, TypeOf } from '@kbn/config-schema';
import { PluginConfigDescriptor } from '@kbn/core/server';
// -------------------------------
@ -15,14 +15,11 @@ const configSchema = schema.object({
/**
* Disables the plugin.
*/
enabled: schema.conditional(
schema.contextRef('serverless'),
true,
enabled: offeringBasedSchema({
// Upgrade Assistant is disabled in serverless; refer to the serverless.yml file as the source of truth
// We take this approach in order to have a central place (serverless.yml) to view disabled plugins across Kibana
schema.boolean({ defaultValue: true }),
schema.never()
),
serverless: schema.boolean({ defaultValue: true }),
}),
featureSet: schema.object({
/**

View file

@ -6,7 +6,7 @@
*/
import { PluginInitializerContext } from '@kbn/core/server';
import { schema } from '@kbn/config-schema';
import { offeringBasedSchema, schema } from '@kbn/config-schema';
import { WatcherServerPlugin } from './plugin';
@ -14,13 +14,10 @@ export const plugin = (ctx: PluginInitializerContext) => new WatcherServerPlugin
export const config = {
schema: schema.object({
enabled: schema.conditional(
schema.contextRef('serverless'),
true,
enabled: offeringBasedSchema({
// Watcher is disabled in serverless; refer to the serverless.yml file as the source of truth
// We take this approach in order to have a central place (serverless.yml) to view disabled plugins across Kibana
schema.boolean({ defaultValue: true }),
schema.never()
),
serverless: schema.boolean({ defaultValue: true }),
}),
}),
};