diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index a017c79309a56c..f2d67498130131 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -76,6 +76,7 @@ /src/plugins/apm_oss/ @elastic/apm-ui /src/apm.js @elastic/kibana-core @vigneshshanmugam /packages/kbn-apm-config-loader/ @elastic/kibana-core @vigneshshanmugam +/src/core/types/elasticsearch @elastic/apm-ui #CC# /src/plugins/apm_oss/ @elastic/apm-ui #CC# /x-pack/plugins/observability/ @elastic/apm-ui diff --git a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md index 9930ab7319f653..d3d76079cdc2a1 100644 --- a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md +++ b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md @@ -185,5 +185,18 @@ readonly links: { readonly plugins: Record; readonly snapshotRestore: Record; readonly ingest: Record; + readonly fleet: Readonly<{ + guide: string; + fleetServer: string; + fleetServerAddFleetServer: string; + settings: string; + settingsFleetServerHostSettings: string; + troubleshooting: string; + elasticAgent: string; + datastreams: string; + datastreamsNamingScheme: string; + upgradeElasticAgent: string; + upgradeElasticAgent712lower: string; + }>; }; ``` diff --git a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md index ab8cdea5e4d869..34279cef198bfb 100644 --- a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md +++ b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md @@ -17,5 +17,5 @@ export interface DocLinksStart | --- | --- | --- | | [DOC\_LINK\_VERSION](./kibana-plugin-core-public.doclinksstart.doc_link_version.md) | string | | | [ELASTIC\_WEBSITE\_URL](./kibana-plugin-core-public.doclinksstart.elastic_website_url.md) | string | | -| [links](./kibana-plugin-core-public.doclinksstart.links.md) | {
readonly canvas: {
readonly guide: string;
};
readonly dashboard: {
readonly guide: string;
readonly drilldowns: string;
readonly drilldownsTriggerPicker: string;
readonly urlDrilldownTemplateSyntax: string;
readonly urlDrilldownVariables: string;
};
readonly discover: Record<string, string>;
readonly filebeat: {
readonly base: string;
readonly installation: string;
readonly configuration: string;
readonly elasticsearchOutput: string;
readonly elasticsearchModule: string;
readonly startup: string;
readonly exportedFields: string;
};
readonly auditbeat: {
readonly base: string;
};
readonly metricbeat: {
readonly base: string;
readonly configure: string;
readonly httpEndpoint: string;
readonly install: string;
readonly start: string;
};
readonly enterpriseSearch: {
readonly base: string;
readonly appSearchBase: string;
readonly workplaceSearchBase: string;
};
readonly heartbeat: {
readonly base: string;
};
readonly logstash: {
readonly base: string;
};
readonly functionbeat: {
readonly base: string;
};
readonly winlogbeat: {
readonly base: string;
};
readonly aggs: {
readonly composite: string;
readonly composite_missing_bucket: string;
readonly date_histogram: string;
readonly date_range: string;
readonly date_format_pattern: string;
readonly filter: string;
readonly filters: string;
readonly geohash_grid: string;
readonly histogram: string;
readonly ip_range: string;
readonly range: string;
readonly significant_terms: string;
readonly terms: string;
readonly avg: string;
readonly avg_bucket: string;
readonly max_bucket: string;
readonly min_bucket: string;
readonly sum_bucket: string;
readonly cardinality: string;
readonly count: string;
readonly cumulative_sum: string;
readonly derivative: string;
readonly geo_bounds: string;
readonly geo_centroid: string;
readonly max: string;
readonly median: string;
readonly min: string;
readonly moving_avg: string;
readonly percentile_ranks: string;
readonly serial_diff: string;
readonly std_dev: string;
readonly sum: string;
readonly top_hits: string;
};
readonly runtimeFields: {
readonly overview: string;
readonly mapping: string;
};
readonly scriptedFields: {
readonly scriptFields: string;
readonly scriptAggs: string;
readonly painless: string;
readonly painlessApi: string;
readonly painlessLangSpec: string;
readonly painlessSyntax: string;
readonly painlessWalkthrough: string;
readonly luceneExpressions: string;
};
readonly search: {
readonly sessions: string;
};
readonly indexPatterns: {
readonly introduction: string;
readonly fieldFormattersNumber: string;
readonly fieldFormattersString: string;
readonly runtimeFields: string;
};
readonly addData: string;
readonly kibana: string;
readonly upgradeAssistant: string;
readonly elasticsearch: Record<string, string>;
readonly siem: {
readonly guide: string;
readonly gettingStarted: string;
};
readonly query: {
readonly eql: string;
readonly kueryQuerySyntax: string;
readonly luceneQuerySyntax: string;
readonly percolate: string;
readonly queryDsl: string;
};
readonly date: {
readonly dateMath: string;
readonly dateMathIndexNames: string;
};
readonly management: Record<string, string>;
readonly ml: Record<string, string>;
readonly transforms: Record<string, string>;
readonly visualize: Record<string, string>;
readonly apis: Readonly<{
bulkIndexAlias: string;
byteSizeUnits: string;
createAutoFollowPattern: string;
createFollower: string;
createIndex: string;
createSnapshotLifecyclePolicy: string;
createRoleMapping: string;
createRoleMappingTemplates: string;
createRollupJobsRequest: string;
createApiKey: string;
createPipeline: string;
createTransformRequest: string;
cronExpressions: string;
executeWatchActionModes: string;
indexExists: string;
openIndex: string;
putComponentTemplate: string;
painlessExecute: string;
painlessExecuteAPIContexts: string;
putComponentTemplateMetadata: string;
putSnapshotLifecyclePolicy: string;
putIndexTemplateV1: string;
putWatch: string;
simulatePipeline: string;
timeUnits: string;
updateTransform: string;
}>;
readonly observability: Record<string, string>;
readonly alerting: Record<string, string>;
readonly maps: Record<string, string>;
readonly monitoring: Record<string, string>;
readonly security: Readonly<{
apiKeyServiceSettings: string;
clusterPrivileges: string;
elasticsearchSettings: string;
elasticsearchEnableSecurity: string;
indicesPrivileges: string;
kibanaTLS: string;
kibanaPrivileges: string;
mappingRoles: string;
mappingRolesFieldRules: string;
runAsPrivilege: string;
}>;
readonly watcher: Record<string, string>;
readonly ccs: Record<string, string>;
readonly plugins: Record<string, string>;
readonly snapshotRestore: Record<string, string>;
readonly ingest: Record<string, string>;
} | | +| [links](./kibana-plugin-core-public.doclinksstart.links.md) | {
readonly canvas: {
readonly guide: string;
};
readonly dashboard: {
readonly guide: string;
readonly drilldowns: string;
readonly drilldownsTriggerPicker: string;
readonly urlDrilldownTemplateSyntax: string;
readonly urlDrilldownVariables: string;
};
readonly discover: Record<string, string>;
readonly filebeat: {
readonly base: string;
readonly installation: string;
readonly configuration: string;
readonly elasticsearchOutput: string;
readonly elasticsearchModule: string;
readonly startup: string;
readonly exportedFields: string;
};
readonly auditbeat: {
readonly base: string;
};
readonly metricbeat: {
readonly base: string;
readonly configure: string;
readonly httpEndpoint: string;
readonly install: string;
readonly start: string;
};
readonly enterpriseSearch: {
readonly base: string;
readonly appSearchBase: string;
readonly workplaceSearchBase: string;
};
readonly heartbeat: {
readonly base: string;
};
readonly logstash: {
readonly base: string;
};
readonly functionbeat: {
readonly base: string;
};
readonly winlogbeat: {
readonly base: string;
};
readonly aggs: {
readonly composite: string;
readonly composite_missing_bucket: string;
readonly date_histogram: string;
readonly date_range: string;
readonly date_format_pattern: string;
readonly filter: string;
readonly filters: string;
readonly geohash_grid: string;
readonly histogram: string;
readonly ip_range: string;
readonly range: string;
readonly significant_terms: string;
readonly terms: string;
readonly avg: string;
readonly avg_bucket: string;
readonly max_bucket: string;
readonly min_bucket: string;
readonly sum_bucket: string;
readonly cardinality: string;
readonly count: string;
readonly cumulative_sum: string;
readonly derivative: string;
readonly geo_bounds: string;
readonly geo_centroid: string;
readonly max: string;
readonly median: string;
readonly min: string;
readonly moving_avg: string;
readonly percentile_ranks: string;
readonly serial_diff: string;
readonly std_dev: string;
readonly sum: string;
readonly top_hits: string;
};
readonly runtimeFields: {
readonly overview: string;
readonly mapping: string;
};
readonly scriptedFields: {
readonly scriptFields: string;
readonly scriptAggs: string;
readonly painless: string;
readonly painlessApi: string;
readonly painlessLangSpec: string;
readonly painlessSyntax: string;
readonly painlessWalkthrough: string;
readonly luceneExpressions: string;
};
readonly search: {
readonly sessions: string;
};
readonly indexPatterns: {
readonly introduction: string;
readonly fieldFormattersNumber: string;
readonly fieldFormattersString: string;
readonly runtimeFields: string;
};
readonly addData: string;
readonly kibana: string;
readonly upgradeAssistant: string;
readonly elasticsearch: Record<string, string>;
readonly siem: {
readonly guide: string;
readonly gettingStarted: string;
};
readonly query: {
readonly eql: string;
readonly kueryQuerySyntax: string;
readonly luceneQuerySyntax: string;
readonly percolate: string;
readonly queryDsl: string;
};
readonly date: {
readonly dateMath: string;
readonly dateMathIndexNames: string;
};
readonly management: Record<string, string>;
readonly ml: Record<string, string>;
readonly transforms: Record<string, string>;
readonly visualize: Record<string, string>;
readonly apis: Readonly<{
bulkIndexAlias: string;
byteSizeUnits: string;
createAutoFollowPattern: string;
createFollower: string;
createIndex: string;
createSnapshotLifecyclePolicy: string;
createRoleMapping: string;
createRoleMappingTemplates: string;
createRollupJobsRequest: string;
createApiKey: string;
createPipeline: string;
createTransformRequest: string;
cronExpressions: string;
executeWatchActionModes: string;
indexExists: string;
openIndex: string;
putComponentTemplate: string;
painlessExecute: string;
painlessExecuteAPIContexts: string;
putComponentTemplateMetadata: string;
putSnapshotLifecyclePolicy: string;
putIndexTemplateV1: string;
putWatch: string;
simulatePipeline: string;
timeUnits: string;
updateTransform: string;
}>;
readonly observability: Record<string, string>;
readonly alerting: Record<string, string>;
readonly maps: Record<string, string>;
readonly monitoring: Record<string, string>;
readonly security: Readonly<{
apiKeyServiceSettings: string;
clusterPrivileges: string;
elasticsearchSettings: string;
elasticsearchEnableSecurity: string;
indicesPrivileges: string;
kibanaTLS: string;
kibanaPrivileges: string;
mappingRoles: string;
mappingRolesFieldRules: string;
runAsPrivilege: string;
}>;
readonly watcher: Record<string, string>;
readonly ccs: Record<string, string>;
readonly plugins: Record<string, string>;
readonly snapshotRestore: Record<string, string>;
readonly ingest: Record<string, string>;
readonly fleet: Readonly<{
guide: string;
fleetServer: string;
fleetServerAddFleetServer: string;
settings: string;
settingsFleetServerHostSettings: string;
troubleshooting: string;
elasticAgent: string;
datastreams: string;
datastreamsNamingScheme: string;
upgradeElasticAgent: string;
upgradeElasticAgent712lower: string;
}>;
} | | diff --git a/docs/development/core/server/kibana-plugin-core-server.md b/docs/development/core/server/kibana-plugin-core-server.md index 604cdea1a7fbe6..ac8930c52ac5c3 100644 --- a/docs/development/core/server/kibana-plugin-core-server.md +++ b/docs/development/core/server/kibana-plugin-core-server.md @@ -165,6 +165,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [SavedObjectsDeleteOptions](./kibana-plugin-core-server.savedobjectsdeleteoptions.md) | | | [SavedObjectsExportByObjectOptions](./kibana-plugin-core-server.savedobjectsexportbyobjectoptions.md) | Options for the [export by objects API](./kibana-plugin-core-server.savedobjectsexporter.exportbyobjects.md) | | [SavedObjectsExportByTypeOptions](./kibana-plugin-core-server.savedobjectsexportbytypeoptions.md) | Options for the [export by type API](./kibana-plugin-core-server.savedobjectsexporter.exportbytypes.md) | +| [SavedObjectsExportExcludedObject](./kibana-plugin-core-server.savedobjectsexportexcludedobject.md) | | | [SavedObjectsExportResultDetails](./kibana-plugin-core-server.savedobjectsexportresultdetails.md) | Structure of the export result details entry | | [SavedObjectsExportTransformContext](./kibana-plugin-core-server.savedobjectsexporttransformcontext.md) | Context passed down to a [export transform function](./kibana-plugin-core-server.savedobjectsexporttransform.md) | | [SavedObjectsFindOptions](./kibana-plugin-core-server.savedobjectsfindoptions.md) | | diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportexcludedobject.id.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportexcludedobject.id.md new file mode 100644 index 00000000000000..f7b96e71c8e53a --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportexcludedobject.id.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsExportExcludedObject](./kibana-plugin-core-server.savedobjectsexportexcludedobject.md) > [id](./kibana-plugin-core-server.savedobjectsexportexcludedobject.id.md) + +## SavedObjectsExportExcludedObject.id property + +id of the excluded object + +Signature: + +```typescript +id: string; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportexcludedobject.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportexcludedobject.md new file mode 100644 index 00000000000000..4766ae25a936df --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportexcludedobject.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsExportExcludedObject](./kibana-plugin-core-server.savedobjectsexportexcludedobject.md) + +## SavedObjectsExportExcludedObject interface + + +Signature: + +```typescript +export interface SavedObjectsExportExcludedObject +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [id](./kibana-plugin-core-server.savedobjectsexportexcludedobject.id.md) | string | id of the excluded object | +| [reason](./kibana-plugin-core-server.savedobjectsexportexcludedobject.reason.md) | string | optional cause of the exclusion | +| [type](./kibana-plugin-core-server.savedobjectsexportexcludedobject.type.md) | string | type of the excluded object | + diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportexcludedobject.reason.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportexcludedobject.reason.md new file mode 100644 index 00000000000000..0adb1ba35e6965 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportexcludedobject.reason.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsExportExcludedObject](./kibana-plugin-core-server.savedobjectsexportexcludedobject.md) > [reason](./kibana-plugin-core-server.savedobjectsexportexcludedobject.reason.md) + +## SavedObjectsExportExcludedObject.reason property + +optional cause of the exclusion + +Signature: + +```typescript +reason?: string; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportexcludedobject.type.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportexcludedobject.type.md new file mode 100644 index 00000000000000..be28ac2d0ffb6d --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportexcludedobject.type.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsExportExcludedObject](./kibana-plugin-core-server.savedobjectsexportexcludedobject.md) > [type](./kibana-plugin-core-server.savedobjectsexportexcludedobject.type.md) + +## SavedObjectsExportExcludedObject.type property + +type of the excluded object + +Signature: + +```typescript +type: string; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportresultdetails.excludedobjects.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportresultdetails.excludedobjects.md new file mode 100644 index 00000000000000..90432bf6d6705b --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportresultdetails.excludedobjects.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsExportResultDetails](./kibana-plugin-core-server.savedobjectsexportresultdetails.md) > [excludedObjects](./kibana-plugin-core-server.savedobjectsexportresultdetails.excludedobjects.md) + +## SavedObjectsExportResultDetails.excludedObjects property + +excluded objects details + +Signature: + +```typescript +excludedObjects: SavedObjectsExportExcludedObject[]; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportresultdetails.excludedobjectscount.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportresultdetails.excludedobjectscount.md new file mode 100644 index 00000000000000..05846e28b9caba --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportresultdetails.excludedobjectscount.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsExportResultDetails](./kibana-plugin-core-server.savedobjectsexportresultdetails.md) > [excludedObjectsCount](./kibana-plugin-core-server.savedobjectsexportresultdetails.excludedobjectscount.md) + +## SavedObjectsExportResultDetails.excludedObjectsCount property + +number of objects that were excluded from the export + +Signature: + +```typescript +excludedObjectsCount: number; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportresultdetails.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportresultdetails.md index d98088c5f45be2..f017f2329170ba 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportresultdetails.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportresultdetails.md @@ -16,6 +16,8 @@ export interface SavedObjectsExportResultDetails | Property | Type | Description | | --- | --- | --- | +| [excludedObjects](./kibana-plugin-core-server.savedobjectsexportresultdetails.excludedobjects.md) | SavedObjectsExportExcludedObject[] | excluded objects details | +| [excludedObjectsCount](./kibana-plugin-core-server.savedobjectsexportresultdetails.excludedobjectscount.md) | number | number of objects that were excluded from the export | | [exportedCount](./kibana-plugin-core-server.savedobjectsexportresultdetails.exportedcount.md) | number | number of successfully exported objects | | [missingRefCount](./kibana-plugin-core-server.savedobjectsexportresultdetails.missingrefcount.md) | number | number of missing references | | [missingReferences](./kibana-plugin-core-server.savedobjectsexportresultdetails.missingreferences.md) | Array<{
id: string;
type: string;
}> | missing references details | diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexporttransform.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexporttransform.md index 50d4c5425e8fd3..2effed1ae9d70e 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexporttransform.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexporttransform.md @@ -11,7 +11,7 @@ A type's export transform function will be executed once per user-initiated expo Signature: ```typescript -export declare type SavedObjectsExportTransform = (context: SavedObjectsExportTransformContext, objects: Array>) => SavedObject[] | Promise; +export declare type SavedObjectsExportTransform = (context: SavedObjectsExportTransformContext, objects: Array>) => SavedObject[] | Promise; ``` ## Remarks diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.md index 56ebb48707f59c..a1bc99ce8d13dc 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.md @@ -52,6 +52,6 @@ export class Plugin() { | Property | Type | Description | | --- | --- | --- | | [addClientWrapper](./kibana-plugin-core-server.savedobjectsservicesetup.addclientwrapper.md) | (priority: number, id: string, factory: SavedObjectsClientWrapperFactory) => void | Add a [client wrapper factory](./kibana-plugin-core-server.savedobjectsclientwrapperfactory.md) with the given priority. | -| [registerType](./kibana-plugin-core-server.savedobjectsservicesetup.registertype.md) | (type: SavedObjectsType) => void | Register a [savedObjects type](./kibana-plugin-core-server.savedobjectstype.md) definition.See the [mappings format](./kibana-plugin-core-server.savedobjectstypemappingdefinition.md) and [migration format](./kibana-plugin-core-server.savedobjectmigrationmap.md) for more details about these. | +| [registerType](./kibana-plugin-core-server.savedobjectsservicesetup.registertype.md) | <Attributes = any>(type: SavedObjectsType<Attributes>) => void | Register a [savedObjects type](./kibana-plugin-core-server.savedobjectstype.md) definition.See the [mappings format](./kibana-plugin-core-server.savedobjectstypemappingdefinition.md) and [migration format](./kibana-plugin-core-server.savedobjectmigrationmap.md) for more details about these. | | [setClientFactoryProvider](./kibana-plugin-core-server.savedobjectsservicesetup.setclientfactoryprovider.md) | (clientFactoryProvider: SavedObjectsClientFactoryProvider) => void | Set the default [factory provider](./kibana-plugin-core-server.savedobjectsclientfactoryprovider.md) for creating Saved Objects clients. Only one provider can be set, subsequent calls to this method will fail. | diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.registertype.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.registertype.md index 54e01d3110a2dd..7f74ce4d7bea75 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.registertype.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.registertype.md @@ -11,7 +11,7 @@ See the [mappings format](./kibana-plugin-core-server.savedobjectstypemappingdef Signature: ```typescript -registerType: (type: SavedObjectsType) => void; +registerType: (type: SavedObjectsType) => void; ``` ## Example diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectstype.management.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectstype.management.md index fbaf58f959075b..d98c553656b1f9 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectstype.management.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectstype.management.md @@ -9,5 +9,5 @@ An optional [saved objects management section](./kibana-plugin-core-server.saved Signature: ```typescript -management?: SavedObjectsTypeManagementDefinition; +management?: SavedObjectsTypeManagementDefinition; ``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectstype.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectstype.md index d882938d731c8c..c3aba5261561ff 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectstype.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectstype.md @@ -7,7 +7,7 @@ Signature: ```typescript -export interface SavedObjectsType +export interface SavedObjectsType ``` ## Remarks @@ -54,7 +54,7 @@ Example after converting to a multi-namespace (shareable) type in 8.1: Note: migration function(s) can be optionally specified for any of these versions and will not interfere with the conversion process. | | [hidden](./kibana-plugin-core-server.savedobjectstype.hidden.md) | boolean | Is the type hidden by default. If true, repositories will not have access to this type unless explicitly declared as an extraType when creating the repository.See [createInternalRepository](./kibana-plugin-core-server.savedobjectsservicestart.createinternalrepository.md). | | [indexPattern](./kibana-plugin-core-server.savedobjectstype.indexpattern.md) | string | If defined, the type instances will be stored in the given index instead of the default one. | -| [management](./kibana-plugin-core-server.savedobjectstype.management.md) | SavedObjectsTypeManagementDefinition | An optional [saved objects management section](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.md) definition for the type. | +| [management](./kibana-plugin-core-server.savedobjectstype.management.md) | SavedObjectsTypeManagementDefinition<Attributes> | An optional [saved objects management section](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.md) definition for the type. | | [mappings](./kibana-plugin-core-server.savedobjectstype.mappings.md) | SavedObjectsTypeMappingDefinition | The [mapping definition](./kibana-plugin-core-server.savedobjectstypemappingdefinition.md) for the type. | | [migrations](./kibana-plugin-core-server.savedobjectstype.migrations.md) | SavedObjectMigrationMap | (() => SavedObjectMigrationMap) | An optional map of [migrations](./kibana-plugin-core-server.savedobjectmigrationfn.md) or a function returning a map of [migrations](./kibana-plugin-core-server.savedobjectmigrationfn.md) to be used to migrate the type. | | [name](./kibana-plugin-core-server.savedobjectstype.name.md) | string | The name of the type, which is also used as the internal id. | diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.getediturl.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.getediturl.md index f5488d8f0310d4..75f820d7a8e56b 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.getediturl.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.getediturl.md @@ -9,5 +9,5 @@ Function returning the url to use to redirect to the editing page of this object Signature: ```typescript -getEditUrl?: (savedObject: SavedObject) => string; +getEditUrl?: (savedObject: SavedObject) => string; ``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.getinappurl.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.getinappurl.md index 7b31dda402571c..d6d50840aaadb6 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.getinappurl.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.getinappurl.md @@ -9,7 +9,7 @@ Function returning the url to use to redirect to this object from the management Signature: ```typescript -getInAppUrl?: (savedObject: SavedObject) => { +getInAppUrl?: (savedObject: SavedObject) => { path: string; uiCapabilitiesPath: string; }; diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.gettitle.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.gettitle.md index 2f39acc66f451e..75784666ef9632 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.gettitle.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.gettitle.md @@ -9,5 +9,5 @@ Function returning the title to display in the management table. If not defined, Signature: ```typescript -getTitle?: (savedObject: SavedObject) => string; +getTitle?: (savedObject: SavedObject) => string; ``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.isexportable.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.isexportable.md new file mode 100644 index 00000000000000..fef178e1d98475 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.isexportable.md @@ -0,0 +1,49 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsTypeManagementDefinition](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.md) > [isExportable](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.isexportable.md) + +## SavedObjectsTypeManagementDefinition.isExportable property + +Optional hook to specify whether an object should be exportable. + +If specified, `isExportable` will be called during export for each of this type's objects in the export, and the ones not matching the predicate will be excluded from the export. + +When implementing both `isExportable` and `onExport`, it is mandatory that `isExportable` returns the same value for an object before and after going though the export transform. E.g `isExportable(objectBeforeTransform) === isExportable(objectAfterTransform)` + +Signature: + +```typescript +isExportable?: SavedObjectsExportablePredicate; +``` + +## Remarks + +`importableAndExportable` must be `true` to specify this property. + +## Example + +Registering a type with a per-object exportability predicate + +```ts +// src/plugins/my_plugin/server/plugin.ts +import { myType } from './saved_objects'; + +export class Plugin() { + setup: (core: CoreSetup) => { + core.savedObjects.registerType({ + ...myType, + management: { + ...myType.management, + isExportable: (object) => { + if (object.attributes.myCustomAttr === 'foo') { + return false; + } + return true; + } + }, + }); + } +} + +``` + diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.md index e9cc2b12108d65..8c42884eb0b317 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.md @@ -9,7 +9,7 @@ Configuration options for the [type](./kibana-plugin-core-server.savedobjectstyp Signature: ```typescript -export interface SavedObjectsTypeManagementDefinition +export interface SavedObjectsTypeManagementDefinition ``` ## Properties @@ -17,11 +17,12 @@ export interface SavedObjectsTypeManagementDefinition | Property | Type | Description | | --- | --- | --- | | [defaultSearchField](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.defaultsearchfield.md) | string | The default search field to use for this type. Defaults to id. | -| [getEditUrl](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.getediturl.md) | (savedObject: SavedObject<any>) => string | Function returning the url to use to redirect to the editing page of this object. If not defined, editing will not be allowed. | -| [getInAppUrl](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.getinappurl.md) | (savedObject: SavedObject<any>) => {
path: string;
uiCapabilitiesPath: string;
} | Function returning the url to use to redirect to this object from the management section. If not defined, redirecting to the object will not be allowed. | -| [getTitle](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.gettitle.md) | (savedObject: SavedObject<any>) => string | Function returning the title to display in the management table. If not defined, will use the object's type and id to generate a label. | +| [getEditUrl](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.getediturl.md) | (savedObject: SavedObject<Attributes>) => string | Function returning the url to use to redirect to the editing page of this object. If not defined, editing will not be allowed. | +| [getInAppUrl](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.getinappurl.md) | (savedObject: SavedObject<Attributes>) => {
path: string;
uiCapabilitiesPath: string;
} | Function returning the url to use to redirect to this object from the management section. If not defined, redirecting to the object will not be allowed. | +| [getTitle](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.gettitle.md) | (savedObject: SavedObject<Attributes>) => string | Function returning the title to display in the management table. If not defined, will use the object's type and id to generate a label. | | [icon](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.icon.md) | string | The eui icon name to display in the management table. If not defined, the default icon will be used. | | [importableAndExportable](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.importableandexportable.md) | boolean | Is the type importable or exportable. Defaults to false. | -| [onExport](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.onexport.md) | SavedObjectsExportTransform | An optional export transform function that can be used transform the objects of the registered type during the export process.It can be used to either mutate the exported objects, or add additional objects (of any type) to the export list.See [the transform type documentation](./kibana-plugin-core-server.savedobjectsexporttransform.md) for more info and examples. | -| [onImport](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.onimport.md) | SavedObjectsImportHook | An optional [import hook](./kibana-plugin-core-server.savedobjectsimporthook.md) to use when importing given type.Import hooks are executed during the savedObjects import process and allow to interact with the imported objects. See the [hook documentation](./kibana-plugin-core-server.savedobjectsimporthook.md) for more info. | +| [isExportable](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.isexportable.md) | SavedObjectsExportablePredicate<Attributes> | Optional hook to specify whether an object should be exportable.If specified, isExportable will be called during export for each of this type's objects in the export, and the ones not matching the predicate will be excluded from the export.When implementing both isExportable and onExport, it is mandatory that isExportable returns the same value for an object before and after going though the export transform. E.g isExportable(objectBeforeTransform) === isExportable(objectAfterTransform) | +| [onExport](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.onexport.md) | SavedObjectsExportTransform<Attributes> | An optional export transform function that can be used transform the objects of the registered type during the export process.It can be used to either mutate the exported objects, or add additional objects (of any type) to the export list.See [the transform type documentation](./kibana-plugin-core-server.savedobjectsexporttransform.md) for more info and examples.When implementing both isExportable and onExport, it is mandatory that isExportable returns the same value for an object before and after going though the export transform. E.g isExportable(objectBeforeTransform) === isExportable(objectAfterTransform) | +| [onImport](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.onimport.md) | SavedObjectsImportHook<Attributes> | An optional [import hook](./kibana-plugin-core-server.savedobjectsimporthook.md) to use when importing given type.Import hooks are executed during the savedObjects import process and allow to interact with the imported objects. See the [hook documentation](./kibana-plugin-core-server.savedobjectsimporthook.md) for more info. | diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.onexport.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.onexport.md index 6302b36a73c681..a0d41d2d649676 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.onexport.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.onexport.md @@ -10,10 +10,12 @@ It can be used to either mutate the exported objects, or add additional objects See [the transform type documentation](./kibana-plugin-core-server.savedobjectsexporttransform.md) for more info and examples. +When implementing both `isExportable` and `onExport`, it is mandatory that `isExportable` returns the same value for an object before and after going though the export transform. E.g `isExportable(objectBeforeTransform) === isExportable(objectAfterTransform)` + Signature: ```typescript -onExport?: SavedObjectsExportTransform; +onExport?: SavedObjectsExportTransform; ``` ## Remarks diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.onimport.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.onimport.md index f6634c01c66bad..332247b8eb8e17 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.onimport.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.onimport.md @@ -11,7 +11,7 @@ Import hooks are executed during the savedObjects import process and allow to in Signature: ```typescript -onImport?: SavedObjectsImportHook; +onImport?: SavedObjectsImportHook; ``` ## Remarks diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.getalltypes.md b/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.getalltypes.md index c839dd16d9a475..20d631ff74acac 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.getalltypes.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.getalltypes.md @@ -11,9 +11,9 @@ To only get the visible types (which is the most common use case), use `getVisib Signature: ```typescript -getAllTypes(): SavedObjectsType[]; +getAllTypes(): SavedObjectsType[]; ``` Returns: -`SavedObjectsType[]` +`SavedObjectsType[]` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.getimportableandexportabletypes.md b/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.getimportableandexportabletypes.md index ab8a79c3a84552..1e29e632a6ec32 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.getimportableandexportabletypes.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.getimportableandexportabletypes.md @@ -9,9 +9,9 @@ Return all [types](./kibana-plugin-core-server.savedobjectstype.md) currently re Signature: ```typescript -getImportableAndExportableTypes(): SavedObjectsType[]; +getImportableAndExportableTypes(): SavedObjectsType[]; ``` Returns: -`SavedObjectsType[]` +`SavedObjectsType[]` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.gettype.md b/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.gettype.md index cfa52882bb89d7..160aadb73cced3 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.gettype.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.gettype.md @@ -9,7 +9,7 @@ Return the [type](./kibana-plugin-core-server.savedobjectstype.md) definition fo Signature: ```typescript -getType(type: string): SavedObjectsType | undefined; +getType(type: string): SavedObjectsType | undefined; ``` ## Parameters @@ -20,5 +20,5 @@ getType(type: string): SavedObjectsType | undefined; Returns: -`SavedObjectsType | undefined` +`SavedObjectsType | undefined` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.getvisibletypes.md b/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.getvisibletypes.md index a773c6a0a674fb..05f22dcf7010bc 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.getvisibletypes.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.getvisibletypes.md @@ -11,9 +11,9 @@ A visible type is a type that doesn't explicitly define `hidden=true` during reg Signature: ```typescript -getVisibleTypes(): SavedObjectsType[]; +getVisibleTypes(): SavedObjectsType[]; ``` Returns: -`SavedObjectsType[]` +`SavedObjectsType[]` diff --git a/docs/management/connectors/action-types/email.asciidoc b/docs/management/connectors/action-types/email.asciidoc index 719d00c16c932a..bab04b80526743 100644 --- a/docs/management/connectors/action-types/email.asciidoc +++ b/docs/management/connectors/action-types/email.asciidoc @@ -95,6 +95,7 @@ The email connector can send email using many popular SMTP email services. For more information about configuring the email connector to work with different email systems, refer to: +* <> * <> * <> * <> @@ -102,6 +103,29 @@ For more information about configuring the email connector to work with differen For other email servers, you can check the list of well-known services that Nodemailer supports in the JSON file https://github.com/nodemailer/nodemailer/blob/master/lib/well-known/services.json[well-known/services.json]. The properties of the objects in those files — `host`, `port`, and `secure` — correspond to the same email connector configuration properties. A missing `secure` property in the "well-known/services.json" file is considered `false`. Typically, `port: 465` uses `secure: true`, and `port: 25` and `port: 587` use `secure: false`. +[float] +[[elasticcloud]] +==== Sending email from Elastic Cloud + +IMPORTANT: These instructions require you to link:{cloud}/ec-watcher.html#ec-watcher-whitelist[whitelist] the email addresses that notifications get sent first. + +Use the following connector settings to send email from Elastic Cloud: + +Sender:: +`noreply@watcheralert.found.io` + +Host:: +`dockerhost` + +Port:: +`10025` + +Secure:: +Toggle off + +Authentication:: +Toggle off + [float] [[gmail]] ==== Sending email from Gmail diff --git a/docs/setup/settings.asciidoc b/docs/setup/settings.asciidoc index ddb906f390a2d9..c3c29adcea18f9 100644 --- a/docs/setup/settings.asciidoc +++ b/docs/setup/settings.asciidoc @@ -325,6 +325,9 @@ The time interval policy will rotate the log file every given interval of time. When `includeElasticMapsService` is turned off, only the vector layers configured by <> and the tile layer configured by <> are available in <>. *Default: `true`* +| `map.emsUrl:` + | Specifies the URL of a self hosted <> + | `map.proxyElasticMapsServiceInMaps:` | Set to `true` to proxy all <> Elastic Maps Service requests through the {kib} server. *Default: `false`* diff --git a/packages/kbn-monaco/src/esql/index.ts b/packages/kbn-monaco/src/esql/index.ts index a3f9df00118b73..4b50a222ad2d6e 100644 --- a/packages/kbn-monaco/src/esql/index.ts +++ b/packages/kbn-monaco/src/esql/index.ts @@ -6,7 +6,8 @@ * Side Public License, v 1. */ +import { LangModule as LangModuleType } from '../types'; import { ID } from './constants'; import { lexerRules } from './lexer_rules'; -export const EsqlLang = { ID, lexerRules }; +export const EsqlLang: LangModuleType = { ID, lexerRules }; diff --git a/packages/kbn-monaco/src/helpers.ts b/packages/kbn-monaco/src/helpers.ts new file mode 100644 index 00000000000000..e525b8c1321329 --- /dev/null +++ b/packages/kbn-monaco/src/helpers.ts @@ -0,0 +1,21 @@ +/* + * 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 { monaco } from './monaco_imports'; +import { LangModule as LangModuleType } from './types'; + +function registerLanguage(language: LangModuleType) { + const { ID, lexerRules, languageConfiguration } = language; + + monaco.languages.register({ id: ID }); + monaco.languages.setMonarchTokensProvider(ID, lexerRules); + if (languageConfiguration) { + monaco.languages.setLanguageConfiguration(ID, languageConfiguration); + } +} + +export { registerLanguage }; diff --git a/packages/kbn-monaco/src/index.ts b/packages/kbn-monaco/src/index.ts index ce35d7c3572e6c..85d3518461a493 100644 --- a/packages/kbn-monaco/src/index.ts +++ b/packages/kbn-monaco/src/index.ts @@ -12,7 +12,13 @@ import './register_globals'; export { monaco } from './monaco_imports'; export { XJsonLang } from './xjson'; export { PainlessLang, PainlessContext, PainlessAutocompleteField } from './painless'; - /* eslint-disable-next-line @kbn/eslint/module_migration */ import * as BarePluginApi from 'monaco-editor/esm/vs/editor/editor.api'; -export { BarePluginApi }; + +import { registerLanguage } from './helpers'; +import { + LangModule as LangModuleType, + CompleteLangModule as CompleteLangModuleType, +} from './types'; + +export { BarePluginApi, registerLanguage, LangModuleType, CompleteLangModuleType }; diff --git a/packages/kbn-monaco/src/painless/index.ts b/packages/kbn-monaco/src/painless/index.ts index 68582097564308..9863204117b120 100644 --- a/packages/kbn-monaco/src/painless/index.ts +++ b/packages/kbn-monaco/src/painless/index.ts @@ -9,8 +9,9 @@ import { ID } from './constants'; import { lexerRules, languageConfiguration } from './lexer_rules'; import { getSuggestionProvider, getSyntaxErrors } from './language'; +import { CompleteLangModule as CompleteLangModuleType } from '../types'; -export const PainlessLang = { +export const PainlessLang: CompleteLangModuleType = { ID, getSuggestionProvider, lexerRules, diff --git a/packages/kbn-monaco/src/register_globals.ts b/packages/kbn-monaco/src/register_globals.ts index 4047ddedeca42d..c6eb68b89e7184 100644 --- a/packages/kbn-monaco/src/register_globals.ts +++ b/packages/kbn-monaco/src/register_globals.ts @@ -10,6 +10,8 @@ import { XJsonLang } from './xjson'; import { PainlessLang } from './painless'; import { EsqlLang } from './esql'; import { monaco } from './monaco_imports'; +import { registerLanguage } from './helpers'; + // @ts-ignore import xJsonWorkerSrc from '!!raw-loader!../../target_web/xjson.editor.worker.js'; // @ts-ignore @@ -20,14 +22,9 @@ import painlessWorkerSrc from '!!raw-loader!../../target_web/painless.editor.wor /** * Register languages and lexer rules */ -monaco.languages.register({ id: XJsonLang.ID }); -monaco.languages.setMonarchTokensProvider(XJsonLang.ID, XJsonLang.lexerRules); -monaco.languages.setLanguageConfiguration(XJsonLang.ID, XJsonLang.languageConfiguration); -monaco.languages.register({ id: PainlessLang.ID }); -monaco.languages.setMonarchTokensProvider(PainlessLang.ID, PainlessLang.lexerRules); -monaco.languages.setLanguageConfiguration(PainlessLang.ID, PainlessLang.languageConfiguration); -monaco.languages.register({ id: EsqlLang.ID }); -monaco.languages.setMonarchTokensProvider(EsqlLang.ID, EsqlLang.lexerRules); +registerLanguage(XJsonLang); +registerLanguage(PainlessLang); +registerLanguage(EsqlLang); /** * Create web workers by language ID diff --git a/packages/kbn-monaco/src/types.ts b/packages/kbn-monaco/src/types.ts new file mode 100644 index 00000000000000..f977ada5b624b4 --- /dev/null +++ b/packages/kbn-monaco/src/types.ts @@ -0,0 +1,22 @@ +/* + * 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 { monaco } from './monaco_imports'; + +export interface LangModule { + ID: string; + lexerRules: monaco.languages.IMonarchLanguage; + languageConfiguration?: monaco.languages.LanguageConfiguration; + getSuggestionProvider?: Function; + getSyntaxErrors?: Function; +} + +export interface CompleteLangModule extends LangModule { + languageConfiguration: monaco.languages.LanguageConfiguration; + getSuggestionProvider: Function; + getSyntaxErrors: Function; +} diff --git a/packages/kbn-monaco/src/xjson/index.ts b/packages/kbn-monaco/src/xjson/index.ts index 5e278795fef128..e9ece97ac00234 100644 --- a/packages/kbn-monaco/src/xjson/index.ts +++ b/packages/kbn-monaco/src/xjson/index.ts @@ -12,5 +12,6 @@ import './language'; import { ID } from './constants'; import { lexerRules, languageConfiguration } from './lexer_rules'; +import { LangModule as LangModuleType } from '../types'; -export const XJsonLang = { ID, lexerRules, languageConfiguration }; +export const XJsonLang: LangModuleType = { ID, lexerRules, languageConfiguration }; diff --git a/src/core/public/doc_links/doc_links_service.ts b/src/core/public/doc_links/doc_links_service.ts index 06277d9351922c..95091a761639b6 100644 --- a/src/core/public/doc_links/doc_links_service.ts +++ b/src/core/public/doc_links/doc_links_service.ts @@ -22,6 +22,7 @@ export class DocLinksService { const ELASTIC_WEBSITE_URL = 'https://www.elastic.co/'; const ELASTICSEARCH_DOCS = `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}/`; const KIBANA_DOCS = `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/`; + const FLEET_DOCS = `${ELASTIC_WEBSITE_URL}guide/en/fleet/${DOC_LINK_VERSION}/`; const PLUGIN_DOCS = `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/plugins/${DOC_LINK_VERSION}/`; return deepFreeze({ @@ -400,6 +401,19 @@ export class DocLinksService { urlDecode: `${ELASTICSEARCH_DOCS}urldecode-processor.html`, userAgent: `${ELASTICSEARCH_DOCS}user-agent-processor.html`, }, + fleet: { + guide: `${FLEET_DOCS}index.html`, + fleetServer: `${FLEET_DOCS}fleet-server.html`, + fleetServerAddFleetServer: `${FLEET_DOCS}fleet-server.html#add-fleet-server`, + settings: `${FLEET_DOCS}fleet-settings.html#fleet-server-hosts-setting`, + settingsFleetServerHostSettings: `${FLEET_DOCS}fleet-settings.html#fleet-server-hosts-setting`, + troubleshooting: `${FLEET_DOCS}fleet-troubleshooting.html`, + elasticAgent: `${FLEET_DOCS}elastic-agent-installation-configuration.html`, + datastreams: `${FLEET_DOCS}data-streams.html`, + datastreamsNamingScheme: `${FLEET_DOCS}data-streams.html#data-streams-naming-scheme`, + upgradeElasticAgent: `${FLEET_DOCS}upgrade-elastic-agent.html`, + upgradeElasticAgent712lower: `${FLEET_DOCS}upgrade-elastic-agent.html#upgrade-7.12-lower`, + }, }, }); } @@ -587,5 +601,18 @@ export interface DocLinksStart { readonly plugins: Record; readonly snapshotRestore: Record; readonly ingest: Record; + readonly fleet: Readonly<{ + guide: string; + fleetServer: string; + fleetServerAddFleetServer: string; + settings: string; + settingsFleetServerHostSettings: string; + troubleshooting: string; + elasticAgent: string; + datastreams: string; + datastreamsNamingScheme: string; + upgradeElasticAgent: string; + upgradeElasticAgent712lower: string; + }>; }; } diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index d3426b50f76143..6cc2b3f321fb7c 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -664,6 +664,19 @@ export interface DocLinksStart { readonly plugins: Record; readonly snapshotRestore: Record; readonly ingest: Record; + readonly fleet: Readonly<{ + guide: string; + fleetServer: string; + fleetServerAddFleetServer: string; + settings: string; + settingsFleetServerHostSettings: string; + troubleshooting: string; + elasticAgent: string; + datastreams: string; + datastreamsNamingScheme: string; + upgradeElasticAgent: string; + upgradeElasticAgent712lower: string; + }>; }; } diff --git a/src/core/server/index.ts b/src/core/server/index.ts index ef1ee69ff529b5..77946e15ef6863 100644 --- a/src/core/server/index.ts +++ b/src/core/server/index.ts @@ -295,6 +295,7 @@ export type { SavedObjectsCreatePointInTimeFinderOptions, SavedObjectsCreateOptions, SavedObjectsExportResultDetails, + SavedObjectsExportExcludedObject, SavedObjectsFindResult, SavedObjectsFindResponse, SavedObjectsImportConflictError, diff --git a/src/core/server/saved_objects/export/apply_export_transforms.test.ts b/src/core/server/saved_objects/export/apply_export_transforms.test.ts index 95c6bd80a1ac34..ed428ef5759a85 100644 --- a/src/core/server/saved_objects/export/apply_export_transforms.test.ts +++ b/src/core/server/saved_objects/export/apply_export_transforms.test.ts @@ -27,6 +27,8 @@ const createTransform = ( implementation: SavedObjectsExportTransform = (ctx, objs) => objs ): jest.MockedFunction => jest.fn(implementation); +const toMap = (record: Record): Map => new Map(Object.entries(record)); + const expectedContext = { request: expect.any(KibanaRequest), }; @@ -49,10 +51,10 @@ describe('applyExportTransforms', () => { await applyExportTransforms({ request, objects: [foo1, bar1, foo2], - transforms: { + transforms: toMap({ foo: fooTransform, bar: barTransform, - }, + }), }); expect(fooTransform).toHaveBeenCalledTimes(1); @@ -71,10 +73,10 @@ describe('applyExportTransforms', () => { await applyExportTransforms({ request, objects: [foo1], - transforms: { + transforms: toMap({ foo: fooTransform, bar: barTransform, - }, + }), }); expect(fooTransform).toHaveBeenCalledTimes(1); @@ -100,10 +102,10 @@ describe('applyExportTransforms', () => { const result = await applyExportTransforms({ request, objects: [foo1, bar1, foo2], - transforms: { + transforms: toMap({ foo: fooTransform, bar: barTransform, - }, + }), }); expect(result).toEqual([foo1, foo2, dolly1, bar1, hello1]); @@ -123,9 +125,9 @@ describe('applyExportTransforms', () => { const result = await applyExportTransforms({ request, objects: [foo1, foo2, bar1, bar2], - transforms: { + transforms: toMap({ foo: fooTransform, - }, + }), }); expect(result).toEqual([foo1, foo2, dolly1, bar1, bar2]); @@ -150,9 +152,9 @@ describe('applyExportTransforms', () => { const result = await applyExportTransforms({ request, objects: [foo1, foo2], - transforms: { + transforms: toMap({ foo: fooTransform, - }, + }), }); expect(result).toEqual([foo1, foo2].map(disableFoo)); @@ -175,10 +177,10 @@ describe('applyExportTransforms', () => { const result = await applyExportTransforms({ request, objects: [foo1, bar1], - transforms: { + transforms: toMap({ foo: fooTransform, bar: barTransform, - }, + }), }); expect(result).toEqual([foo1, dolly1, bar1, hello1]); @@ -201,10 +203,10 @@ describe('applyExportTransforms', () => { const result = await applyExportTransforms({ request, objects: [foo1, bar1], - transforms: { + transforms: toMap({ foo: fooTransform, bar: barTransform, - }, + }), sortFunction: (obj1, obj2) => (obj1.id > obj2.id ? 1 : -1), }); @@ -223,9 +225,9 @@ describe('applyExportTransforms', () => { applyExportTransforms({ request, objects: [foo1, foo2], - transforms: { + transforms: toMap({ foo: fooTransform, - }, + }), }) ).rejects.toThrowErrorMatchingInlineSnapshot( `"Invalid transform performed on objects to export"` @@ -247,9 +249,9 @@ describe('applyExportTransforms', () => { applyExportTransforms({ request, objects: [foo1, foo2], - transforms: { + transforms: toMap({ foo: fooTransform, - }, + }), }) ).rejects.toThrowErrorMatchingInlineSnapshot( `"Invalid transform performed on objects to export"` @@ -271,9 +273,9 @@ describe('applyExportTransforms', () => { applyExportTransforms({ request, objects: [foo1, foo2], - transforms: { + transforms: toMap({ foo: fooTransform, - }, + }), }) ).rejects.toThrowErrorMatchingInlineSnapshot( `"Invalid transform performed on objects to export"` @@ -291,9 +293,9 @@ describe('applyExportTransforms', () => { applyExportTransforms({ request, objects: [foo1], - transforms: { + transforms: toMap({ foo: fooTransform, - }, + }), }) ).rejects.toThrowErrorMatchingInlineSnapshot(`"Error transforming objects to export"`); }); diff --git a/src/core/server/saved_objects/export/apply_export_transforms.ts b/src/core/server/saved_objects/export/apply_export_transforms.ts index 2a788a32b92f6a..78e1dd7d6c1173 100644 --- a/src/core/server/saved_objects/export/apply_export_transforms.ts +++ b/src/core/server/saved_objects/export/apply_export_transforms.ts @@ -15,7 +15,7 @@ import { getObjKey, SavedObjectComparator } from './utils'; interface ApplyExportTransformsOptions { objects: SavedObject[]; request: KibanaRequest; - transforms: Record; + transforms: Map; sortFunction?: SavedObjectComparator; } @@ -30,7 +30,7 @@ export const applyExportTransforms = async ({ let finalObjects: SavedObject[] = []; for (const [type, typeObjs] of Object.entries(byType)) { - const typeTransformFn = transforms[type]; + const typeTransformFn = transforms.get(type); if (typeTransformFn) { finalObjects = [ ...finalObjects, diff --git a/src/core/server/saved_objects/export/collect_exported_objects.test.ts b/src/core/server/saved_objects/export/collect_exported_objects.test.ts index 0929ff0d40910d..aab9f9134ee2c1 100644 --- a/src/core/server/saved_objects/export/collect_exported_objects.test.ts +++ b/src/core/server/saved_objects/export/collect_exported_objects.test.ts @@ -9,9 +9,12 @@ import { applyExportTransformsMock } from './collect_exported_objects.test.mocks'; import { savedObjectsClientMock } from '../../mocks'; import { httpServerMock } from '../../http/http_server.mocks'; +import { loggerMock } from '../../logging/logger.mock'; import { SavedObject, SavedObjectError } from '../../../types'; +import { SavedObjectTypeRegistry } from '../saved_objects_type_registry'; import type { SavedObjectsExportTransform } from './types'; -import { collectExportedObjects } from './collect_exported_objects'; +import { collectExportedObjects, ExclusionReason } from './collect_exported_objects'; +import { SavedObjectsExportablePredicate } from '../types'; const createObject = (parts: Partial): SavedObject => ({ id: 'id', @@ -29,14 +32,48 @@ const createError = (parts: Partial = {}): SavedObjectError => }); const toIdTuple = (obj: SavedObject) => ({ type: obj.type, id: obj.id }); +const toExcludedObject = (obj: SavedObject, reason: ExclusionReason = 'excluded') => ({ + type: obj.type, + id: obj.id, + reason, +}); + +const toMap = (record: Record): Map => new Map(Object.entries(record)); describe('collectExportedObjects', () => { let savedObjectsClient: ReturnType; let request: ReturnType; + let logger: ReturnType; + let typeRegistry: SavedObjectTypeRegistry; + + const registerType = ( + name: string, + { + onExport, + isExportable, + }: { + onExport?: SavedObjectsExportTransform; + isExportable?: SavedObjectsExportablePredicate; + } = {} + ) => { + typeRegistry.registerType({ + name, + hidden: false, + namespaceType: 'single', + mappings: { properties: {} }, + management: { + importableAndExportable: true, + onExport, + isExportable, + }, + }); + }; beforeEach(() => { + typeRegistry = new SavedObjectTypeRegistry(); savedObjectsClient = savedObjectsClientMock.create(); request = httpServerMock.createKibanaRequest(); + logger = loggerMock.create(); applyExportTransformsMock.mockImplementation(({ objects }) => objects); savedObjectsClient.bulkGet.mockResolvedValue({ saved_objects: [] }); }); @@ -58,23 +95,62 @@ describe('collectExportedObjects', () => { }); const fooTransform: SavedObjectsExportTransform = jest.fn(); + registerType('foo', { onExport: fooTransform }); await collectExportedObjects({ objects: [obj1, obj2], savedObjectsClient, request, - exportTransforms: { foo: fooTransform }, + typeRegistry, includeReferences: true, + logger, }); expect(applyExportTransformsMock).toHaveBeenCalledTimes(1); expect(applyExportTransformsMock).toHaveBeenCalledWith({ objects: [obj1, obj2], - transforms: { foo: fooTransform }, + transforms: toMap({ foo: fooTransform }), request, }); }); + it('calls `isExportable` with the correct parameters', async () => { + const foo1 = createObject({ + type: 'foo', + id: '1', + }); + const foo2 = createObject({ + type: 'foo', + id: '2', + }); + const bar3 = createObject({ + type: 'bar', + id: '3', + }); + + const fooExportable: SavedObjectsExportablePredicate = jest.fn().mockReturnValue(true); + registerType('foo', { isExportable: fooExportable }); + + const barExportable: SavedObjectsExportablePredicate = jest.fn().mockReturnValue(true); + registerType('bar', { isExportable: barExportable }); + + await collectExportedObjects({ + objects: [foo1, foo2, bar3], + savedObjectsClient, + request, + typeRegistry, + includeReferences: true, + logger, + }); + + expect(fooExportable).toHaveBeenCalledTimes(2); + expect(fooExportable).toHaveBeenCalledWith(foo1); + expect(fooExportable).toHaveBeenCalledWith(foo2); + + expect(barExportable).toHaveBeenCalledTimes(1); + expect(barExportable).toHaveBeenCalledWith(bar3); + }); + it('returns the collected objects', async () => { const foo1 = createObject({ type: 'foo', @@ -96,6 +172,10 @@ describe('collectExportedObjects', () => { id: '3', }); + registerType('foo'); + registerType('bar'); + registerType('dolly'); + applyExportTransformsMock.mockImplementationOnce(({ objects }) => [...objects, dolly3]); savedObjectsClient.bulkGet.mockResolvedValueOnce({ saved_objects: [bar2], @@ -105,14 +185,220 @@ describe('collectExportedObjects', () => { objects: [foo1], savedObjectsClient, request, - exportTransforms: {}, + typeRegistry, includeReferences: true, + logger, }); expect(missingRefs).toHaveLength(0); expect(objects.map(toIdTuple)).toEqual([foo1, dolly3, bar2].map(toIdTuple)); }); + it('excludes objects filtered by the `isExportable` predicate', async () => { + const foo1 = createObject({ + type: 'foo', + id: '1', + }); + const foo2 = createObject({ + type: 'foo', + id: '2', + }); + const bar3 = createObject({ + type: 'bar', + id: '3', + }); + + registerType('foo', { isExportable: (obj) => obj.id !== '2' }); + registerType('bar', { isExportable: () => true }); + + const { objects, excludedObjects } = await collectExportedObjects({ + objects: [foo1, foo2, bar3], + savedObjectsClient, + request, + typeRegistry, + includeReferences: true, + logger, + }); + + expect(objects).toEqual([foo1, bar3]); + expect(excludedObjects).toEqual([foo2].map((obj) => toExcludedObject(obj))); + }); + + it('excludes objects when the predicate throws', async () => { + const foo1 = createObject({ + type: 'foo', + id: '1', + }); + const foo2 = createObject({ + type: 'foo', + id: '2', + }); + const bar3 = createObject({ + type: 'bar', + id: '3', + }); + + registerType('foo', { + isExportable: (obj) => { + if (obj.id === '1') { + throw new Error('reason'); + } + return true; + }, + }); + registerType('bar', { isExportable: () => true }); + + const { objects, excludedObjects } = await collectExportedObjects({ + objects: [foo1, foo2, bar3], + savedObjectsClient, + request, + typeRegistry, + includeReferences: true, + logger, + }); + + expect(objects).toEqual([foo2, bar3]); + expect(excludedObjects).toEqual( + [foo1].map((obj) => toExcludedObject(obj, 'predicate_error')) + ); + }); + + it('logs an error for each predicate error', async () => { + const foo1 = createObject({ + type: 'foo', + id: '1', + }); + const foo2 = createObject({ + type: 'foo', + id: '2', + }); + const foo3 = createObject({ + type: 'foo', + id: '3', + }); + + registerType('foo', { + isExportable: (obj) => { + if (obj.id !== '2') { + throw new Error('reason'); + } + return true; + }, + }); + + const { objects, excludedObjects } = await collectExportedObjects({ + objects: [foo1, foo2, foo3], + savedObjectsClient, + request, + typeRegistry, + includeReferences: true, + logger, + }); + + expect(objects).toEqual([foo2]); + expect(excludedObjects).toEqual( + [foo1, foo3].map((obj) => toExcludedObject(obj, 'predicate_error')) + ); + + expect(logger.error).toHaveBeenCalledTimes(2); + const logMessages = logger.error.mock.calls.map((call) => call[0]); + + expect( + (logMessages[0] as string).startsWith( + `Error invoking "isExportable" for object foo:1. Error was: Error: reason` + ) + ).toBe(true); + expect( + (logMessages[1] as string).startsWith( + `Error invoking "isExportable" for object foo:3. Error was: Error: reason` + ) + ).toBe(true); + }); + + it('excludes references filtered by the `isExportable` predicate', async () => { + const foo1 = createObject({ + type: 'foo', + id: '1', + references: [ + { + type: 'bar', + id: '2', + name: 'bar-2', + }, + { + type: 'excluded', + id: '1', + name: 'excluded-1', + }, + ], + }); + const bar2 = createObject({ + type: 'bar', + id: '2', + }); + const excluded1 = createObject({ + type: 'excluded', + id: '1', + }); + + registerType('foo'); + registerType('bar'); + registerType('excluded', { isExportable: () => false }); + + savedObjectsClient.bulkGet.mockResolvedValueOnce({ + saved_objects: [bar2, excluded1], + }); + + const { objects, excludedObjects } = await collectExportedObjects({ + objects: [foo1], + savedObjectsClient, + request, + typeRegistry, + includeReferences: true, + logger, + }); + + expect(objects).toEqual([foo1, bar2]); + expect(excludedObjects).toEqual([excluded1].map((obj) => toExcludedObject(obj))); + }); + + it('excludes additional objects filtered by the `isExportable` predicate', async () => { + const foo1 = createObject({ + type: 'foo', + id: '1', + }); + const bar2 = createObject({ + type: 'bar', + id: '2', + }); + const excluded1 = createObject({ + type: 'excluded', + id: '1', + }); + + registerType('foo'); + registerType('bar'); + registerType('excluded', { isExportable: () => false }); + + applyExportTransformsMock.mockImplementationOnce(({ objects }) => [ + ...objects, + bar2, + excluded1, + ]); + + const { objects, excludedObjects } = await collectExportedObjects({ + objects: [foo1], + savedObjectsClient, + request, + typeRegistry, + includeReferences: true, + logger, + }); + + expect(objects).toEqual([foo1, bar2]); + expect(excludedObjects).toEqual([excluded1].map((obj) => toExcludedObject(obj))); + }); + it('returns the missing references', async () => { const foo1 = createObject({ type: 'foo', @@ -163,8 +449,9 @@ describe('collectExportedObjects', () => { objects: [foo1], savedObjectsClient, request, - exportTransforms: {}, + typeRegistry, includeReferences: true, + logger, }); expect(missingRefs).toEqual([missing1, missing2].map(toIdTuple)); @@ -185,8 +472,9 @@ describe('collectExportedObjects', () => { objects: [obj1, obj2], savedObjectsClient, request, - exportTransforms: {}, + typeRegistry, includeReferences: true, + logger, }); expect(missingRefs).toHaveLength(0); @@ -228,8 +516,9 @@ describe('collectExportedObjects', () => { objects: [foo1], savedObjectsClient, request, - exportTransforms: {}, + typeRegistry, includeReferences: true, + logger, }); expect(savedObjectsClient.bulkGet).toHaveBeenCalledTimes(1); @@ -241,12 +530,12 @@ describe('collectExportedObjects', () => { expect(applyExportTransformsMock).toHaveBeenCalledTimes(2); expect(applyExportTransformsMock).toHaveBeenCalledWith({ objects: [foo1], - transforms: {}, + transforms: toMap({}), request, }); expect(applyExportTransformsMock).toHaveBeenCalledWith({ objects: [bar2], - transforms: {}, + transforms: toMap({}), request, }); }); @@ -302,8 +591,9 @@ describe('collectExportedObjects', () => { objects: [foo1], savedObjectsClient, request, - exportTransforms: {}, + typeRegistry, includeReferences: true, + logger, }); expect(savedObjectsClient.bulkGet).toHaveBeenCalledTimes(2); @@ -366,8 +656,9 @@ describe('collectExportedObjects', () => { objects: [foo1, bar2], savedObjectsClient, request, - exportTransforms: {}, + typeRegistry, includeReferences: true, + logger, }); expect(savedObjectsClient.bulkGet).toHaveBeenCalledTimes(1); @@ -411,8 +702,9 @@ describe('collectExportedObjects', () => { objects: [foo1], savedObjectsClient, request, - exportTransforms: {}, + typeRegistry, includeReferences: true, + logger, }); expect(savedObjectsClient.bulkGet).toHaveBeenCalledTimes(1); @@ -474,8 +766,9 @@ describe('collectExportedObjects', () => { objects: [foo1], savedObjectsClient, request, - exportTransforms: {}, + typeRegistry, includeReferences: true, + logger, }); expect(savedObjectsClient.bulkGet).toHaveBeenCalledTimes(2); @@ -490,6 +783,67 @@ describe('collectExportedObjects', () => { expect.any(Object) ); }); + + it('excludes references filtered by the `isExportable` predicate for additional objects returned by the export transform', async () => { + const foo1 = createObject({ + type: 'foo', + id: '1', + }); + const bar2 = createObject({ + type: 'bar', + id: '2', + references: [ + { + type: 'dolly', + id: '3', + name: 'dolly-3', + }, + { + type: 'baz', + id: '4', + name: 'baz-4', + }, + ], + }); + const dolly3 = createObject({ + type: 'dolly', + id: '3', + references: [ + { + type: 'baz', + id: '4', + name: 'baz-4', + }, + ], + }); + const baz4 = createObject({ + type: 'baz', + id: '4', + }); + + registerType('foo'); + registerType('bar'); + registerType('dolly'); + registerType('baz', { isExportable: () => false }); + + applyExportTransformsMock.mockImplementationOnce(({ objects }) => [...objects, bar2]); + + savedObjectsClient.bulkGet.mockResolvedValueOnce({ + saved_objects: [dolly3, baz4], + }); + + const { objects, excludedObjects } = await collectExportedObjects({ + objects: [foo1], + savedObjectsClient, + request, + typeRegistry, + includeReferences: true, + logger, + }); + + expect(objects).toEqual([foo1, bar2, dolly3]); + expect(excludedObjects).toEqual([baz4].map((obj) => toExcludedObject(obj))); + }); }); describe('when `includeReferences` is `false`', () => { @@ -510,8 +864,9 @@ describe('collectExportedObjects', () => { objects: [obj1], savedObjectsClient, request, - exportTransforms: {}, + typeRegistry, includeReferences: false, + logger, }); expect(missingRefs).toHaveLength(0); diff --git a/src/core/server/saved_objects/export/collect_exported_objects.ts b/src/core/server/saved_objects/export/collect_exported_objects.ts index d45782a83c2844..4789fd3bff67fe 100644 --- a/src/core/server/saved_objects/export/collect_exported_objects.ts +++ b/src/core/server/saved_objects/export/collect_exported_objects.ts @@ -8,7 +8,9 @@ import type { SavedObject } from '../../../types'; import type { KibanaRequest } from '../../http'; -import { SavedObjectsClientContract } from '../types'; +import type { Logger } from '../../logging'; +import { SavedObjectsClientContract, SavedObjectsExportablePredicate } from '../types'; +import { ISavedObjectTypeRegistry } from '../saved_objects_type_registry'; import type { SavedObjectsExportTransform } from './types'; import { applyExportTransforms } from './apply_export_transforms'; @@ -22,41 +24,80 @@ interface CollectExportedObjectOptions { /** The http request initiating the export. */ request: KibanaRequest; /** export transform per type */ - exportTransforms: Record; + typeRegistry: ISavedObjectTypeRegistry; + /** logger to use to log potential errors */ + logger: Logger; } interface CollectExportedObjectResult { objects: SavedObject[]; + excludedObjects: ExcludedObject[]; missingRefs: CollectedReference[]; } +interface ExcludedObject { + id: string; + type: string; + reason: ExclusionReason; +} + +export type ExclusionReason = 'predicate_error' | 'excluded'; + export const collectExportedObjects = async ({ objects, includeReferences = true, namespace, request, - exportTransforms, + typeRegistry, savedObjectsClient, + logger, }: CollectExportedObjectOptions): Promise => { + const exportTransforms = buildTransforms(typeRegistry); + const isExportable = buildIsExportable(typeRegistry); + const collectedObjects: SavedObject[] = []; const collectedMissingRefs: CollectedReference[] = []; + const collectedNonExportableObjects: ExcludedObject[] = []; const alreadyProcessed: Set = new Set(); let currentObjects = objects; do { - const transformed = ( + currentObjects = currentObjects.filter((object) => !alreadyProcessed.has(objKey(object))); + + // first, evict current objects that are not exportable + const { + exportable: untransformedExportableInitialObjects, + nonExportable: nonExportableInitialObjects, + } = await splitByExportability(currentObjects, isExportable, logger); + collectedNonExportableObjects.push(...nonExportableInitialObjects); + nonExportableInitialObjects.forEach((obj) => alreadyProcessed.add(objKey(obj))); + + // second, apply export transforms to exportable objects + const transformedObjects = ( await applyExportTransforms({ request, - objects: currentObjects, + objects: untransformedExportableInitialObjects, transforms: exportTransforms, }) ).filter((object) => !alreadyProcessed.has(objKey(object))); + transformedObjects.forEach((obj) => alreadyProcessed.add(objKey(obj))); - transformed.forEach((obj) => alreadyProcessed.add(objKey(obj))); - collectedObjects.push(...transformed); + // last, evict additional objects that are not exportable + const { included: exportableInitialObjects, excluded: additionalObjects } = splitByKeys( + transformedObjects, + untransformedExportableInitialObjects.map((obj) => objKey(obj)) + ); + const { + exportable: exportableAdditionalObjects, + nonExportable: nonExportableAdditionalObjects, + } = await splitByExportability(additionalObjects, isExportable, logger); + const allExportableObjects = [...exportableInitialObjects, ...exportableAdditionalObjects]; + collectedNonExportableObjects.push(...nonExportableAdditionalObjects); + collectedObjects.push(...allExportableObjects); + // if `includeReferences` is true, recurse on exportable objects' references. if (includeReferences) { - const references = collectReferences(transformed, alreadyProcessed); + const references = collectReferences(allExportableObjects, alreadyProcessed); if (references.length) { const { objects: fetchedObjects, missingRefs } = await fetchReferences({ references, @@ -75,6 +116,7 @@ export const collectExportedObjects = async ({ return { objects: collectedObjects, + excludedObjects: collectedNonExportableObjects, missingRefs: collectedMissingRefs, }; }; @@ -126,3 +168,83 @@ const fetchReferences = async ({ .map((obj) => ({ type: obj.type, id: obj.id })), }; }; + +const buildTransforms = (typeRegistry: ISavedObjectTypeRegistry) => + typeRegistry.getAllTypes().reduce((transformMap, type) => { + if (type.management?.onExport) { + transformMap.set(type.name, type.management.onExport); + } + return transformMap; + }, new Map()); + +const buildIsExportable = ( + typeRegistry: ISavedObjectTypeRegistry +): SavedObjectsExportablePredicate => { + const exportablePerType = typeRegistry.getAllTypes().reduce((exportableMap, type) => { + if (type.management?.isExportable) { + exportableMap.set(type.name, type.management.isExportable); + } + return exportableMap; + }, new Map()); + + return (obj: SavedObject) => { + const typePredicate = exportablePerType.get(obj.type); + return typePredicate ? typePredicate(obj) : true; + }; +}; + +const splitByExportability = ( + objects: SavedObject[], + isExportable: SavedObjectsExportablePredicate, + logger: Logger +) => { + const exportableObjects: SavedObject[] = []; + const nonExportableObjects: ExcludedObject[] = []; + + objects.forEach((obj) => { + try { + const exportable = isExportable(obj); + if (exportable) { + exportableObjects.push(obj); + } else { + nonExportableObjects.push({ + id: obj.id, + type: obj.type, + reason: 'excluded', + }); + } + } catch (e) { + logger.error( + `Error invoking "isExportable" for object ${obj.type}:${obj.id}. Error was: ${ + e.stack ?? e.message + }` + ); + nonExportableObjects.push({ + id: obj.id, + type: obj.type, + reason: 'predicate_error', + }); + } + }); + + return { + exportable: exportableObjects, + nonExportable: nonExportableObjects, + }; +}; + +const splitByKeys = (objects: SavedObject[], keys: ObjectKey[]) => { + const included: SavedObject[] = []; + const excluded: SavedObject[] = []; + objects.forEach((obj) => { + if (keys.includes(objKey(obj))) { + included.push(obj); + } else { + excluded.push(obj); + } + }); + return { + included, + excluded, + }; +}; diff --git a/src/core/server/saved_objects/export/index.ts b/src/core/server/saved_objects/export/index.ts index 4af184e54b49c5..d9b48ce4311175 100644 --- a/src/core/server/saved_objects/export/index.ts +++ b/src/core/server/saved_objects/export/index.ts @@ -13,6 +13,7 @@ export type { SavedObjectsExportResultDetails, SavedObjectsExportTransformContext, SavedObjectsExportTransform, + SavedObjectsExportExcludedObject, } from './types'; export { SavedObjectsExporter } from './saved_objects_exporter'; export type { ISavedObjectsExporter } from './saved_objects_exporter'; diff --git a/src/core/server/saved_objects/export/saved_objects_exporter.test.ts b/src/core/server/saved_objects/export/saved_objects_exporter.test.ts index 6bdb8003de49dd..5968c8dabe8a85 100644 --- a/src/core/server/saved_objects/export/saved_objects_exporter.test.ts +++ b/src/core/server/saved_objects/export/saved_objects_exporter.test.ts @@ -77,32 +77,34 @@ describe('getSortedObjectsForExport()', () => { const response = await readStreamToCompletion(exportStream); expect(response).toMatchInlineSnapshot(` - Array [ - Object { - "attributes": Object {}, - "id": "1", - "references": Array [], - "type": "index-pattern", - }, - Object { - "attributes": Object {}, - "id": "2", - "references": Array [ - Object { - "id": "1", - "name": "name", - "type": "index-pattern", - }, - ], - "type": "search", - }, - Object { - "exportedCount": 2, - "missingRefCount": 0, - "missingReferences": Array [], - }, - ] - `); + Array [ + Object { + "attributes": Object {}, + "id": "1", + "references": Array [], + "type": "index-pattern", + }, + Object { + "attributes": Object {}, + "id": "2", + "references": Array [ + Object { + "id": "1", + "name": "name", + "type": "index-pattern", + }, + ], + "type": "search", + }, + Object { + "excludedObjects": Array [], + "excludedObjectsCount": 0, + "exportedCount": 2, + "missingRefCount": 0, + "missingReferences": Array [], + }, + ] + `); expect(savedObjectsClient.find).toMatchInlineSnapshot(` [MockFunction] { "calls": Array [ @@ -185,6 +187,8 @@ describe('getSortedObjectsForExport()', () => { expect(savedObjectsClient.find).toHaveBeenCalledTimes(1); expect(response[response.length - 1]).toMatchInlineSnapshot(` Object { + "excludedObjects": Array [], + "excludedObjectsCount": 0, "exportedCount": 20, "missingRefCount": 0, "missingReferences": Array [], @@ -269,6 +273,8 @@ describe('getSortedObjectsForExport()', () => { expect(savedObjectsClient.find).toHaveBeenCalledTimes(2); expect(response[response.length - 1]).toMatchInlineSnapshot(` Object { + "excludedObjects": Array [], + "excludedObjectsCount": 0, "exportedCount": 1500, "missingRefCount": 0, "missingReferences": Array [], @@ -422,32 +428,34 @@ describe('getSortedObjectsForExport()', () => { const response = await readStreamToCompletion(exportStream); expect(response).toMatchInlineSnapshot(` - Array [ - Object { - "attributes": Object {}, - "id": "1", - "references": Array [], - "type": "index-pattern", - }, - Object { - "attributes": Object {}, - "id": "2", - "references": Array [ - Object { - "id": "1", - "name": "name", - "type": "index-pattern", - }, - ], - "type": "search", - }, - Object { - "exportedCount": 2, - "missingRefCount": 0, - "missingReferences": Array [], - }, - ] - `); + Array [ + Object { + "attributes": Object {}, + "id": "1", + "references": Array [], + "type": "index-pattern", + }, + Object { + "attributes": Object {}, + "id": "2", + "references": Array [ + Object { + "id": "1", + "name": "name", + "type": "index-pattern", + }, + ], + "type": "search", + }, + Object { + "excludedObjects": Array [], + "excludedObjectsCount": 0, + "exportedCount": 2, + "missingRefCount": 0, + "missingReferences": Array [], + }, + ] + `); expect(savedObjectsClient.find).toMatchInlineSnapshot(` [MockFunction] { "calls": Array [ @@ -579,32 +587,34 @@ describe('getSortedObjectsForExport()', () => { const response = await readStreamToCompletion(exportStream); expect(response).toMatchInlineSnapshot(` - Array [ - Object { - "attributes": Object {}, - "id": "1", - "references": Array [], - "type": "index-pattern", - }, - Object { - "attributes": Object {}, - "id": "2", - "references": Array [ - Object { - "id": "1", - "name": "name", - "type": "index-pattern", - }, - ], - "type": "search", - }, - Object { - "exportedCount": 2, - "missingRefCount": 0, - "missingReferences": Array [], - }, - ] - `); + Array [ + Object { + "attributes": Object {}, + "id": "1", + "references": Array [], + "type": "index-pattern", + }, + Object { + "attributes": Object {}, + "id": "2", + "references": Array [ + Object { + "id": "1", + "name": "name", + "type": "index-pattern", + }, + ], + "type": "search", + }, + Object { + "excludedObjects": Array [], + "excludedObjectsCount": 0, + "exportedCount": 2, + "missingRefCount": 0, + "missingReferences": Array [], + }, + ] + `); expect(savedObjectsClient.find).toMatchInlineSnapshot(` [MockFunction] { "calls": Array [ @@ -674,26 +684,28 @@ describe('getSortedObjectsForExport()', () => { const response = await readStreamToCompletion(exportStream); expect(response).toMatchInlineSnapshot(` - Array [ - Object { - "attributes": Object {}, - "id": "2", - "references": Array [ - Object { - "id": "1", - "name": "name", - "type": "index-pattern", - }, - ], - "type": "search", - }, - Object { - "exportedCount": 1, - "missingRefCount": 0, - "missingReferences": Array [], - }, - ] - `); + Array [ + Object { + "attributes": Object {}, + "id": "2", + "references": Array [ + Object { + "id": "1", + "name": "name", + "type": "index-pattern", + }, + ], + "type": "search", + }, + Object { + "excludedObjects": Array [], + "excludedObjectsCount": 0, + "exportedCount": 1, + "missingRefCount": 0, + "missingReferences": Array [], + }, + ] + `); expect(savedObjectsClient.find).toMatchInlineSnapshot(` [MockFunction] { "calls": Array [ @@ -770,32 +782,34 @@ describe('getSortedObjectsForExport()', () => { const response = await readStreamToCompletion(exportStream); expect(response).toMatchInlineSnapshot(` - Array [ - Object { - "attributes": Object {}, - "id": "1", - "references": Array [], - "type": "index-pattern", - }, - Object { - "attributes": Object {}, - "id": "2", - "references": Array [ - Object { - "id": "1", - "name": "name", - "type": "index-pattern", - }, - ], - "type": "search", - }, - Object { - "exportedCount": 2, - "missingRefCount": 0, - "missingReferences": Array [], - }, - ] - `); + Array [ + Object { + "attributes": Object {}, + "id": "1", + "references": Array [], + "type": "index-pattern", + }, + Object { + "attributes": Object {}, + "id": "2", + "references": Array [ + Object { + "id": "1", + "name": "name", + "type": "index-pattern", + }, + ], + "type": "search", + }, + Object { + "excludedObjects": Array [], + "excludedObjectsCount": 0, + "exportedCount": 2, + "missingRefCount": 0, + "missingReferences": Array [], + }, + ] + `); expect(savedObjectsClient.find).toMatchInlineSnapshot(` [MockFunction] { "calls": Array [ @@ -929,38 +943,40 @@ describe('getSortedObjectsForExport()', () => { }); const response = await readStreamToCompletion(exportStream); expect(response).toMatchInlineSnapshot(` - Array [ - Object { - "attributes": Object { - "name": "foo", - }, - "id": "1", - "references": Array [], - "type": "index-pattern", - }, - Object { - "attributes": Object { - "name": "bar", - }, - "id": "2", - "references": Array [], - "type": "index-pattern", - }, - Object { - "attributes": Object { - "name": "baz", - }, - "id": "3", - "references": Array [], - "type": "index-pattern", - }, - Object { - "exportedCount": 3, - "missingRefCount": 0, - "missingReferences": Array [], - }, - ] - `); + Array [ + Object { + "attributes": Object { + "name": "foo", + }, + "id": "1", + "references": Array [], + "type": "index-pattern", + }, + Object { + "attributes": Object { + "name": "bar", + }, + "id": "2", + "references": Array [], + "type": "index-pattern", + }, + Object { + "attributes": Object { + "name": "baz", + }, + "id": "3", + "references": Array [], + "type": "index-pattern", + }, + Object { + "excludedObjects": Array [], + "excludedObjectsCount": 0, + "exportedCount": 3, + "missingRefCount": 0, + "missingReferences": Array [], + }, + ] + `); }); }); @@ -1003,32 +1019,34 @@ describe('getSortedObjectsForExport()', () => { }); const response = await readStreamToCompletion(exportStream); expect(response).toMatchInlineSnapshot(` - Array [ - Object { - "attributes": Object {}, - "id": "1", - "references": Array [], - "type": "index-pattern", - }, - Object { - "attributes": Object {}, - "id": "2", - "references": Array [ - Object { - "id": "1", - "name": "name", - "type": "index-pattern", - }, - ], - "type": "search", - }, - Object { - "exportedCount": 2, - "missingRefCount": 0, - "missingReferences": Array [], - }, - ] - `); + Array [ + Object { + "attributes": Object {}, + "id": "1", + "references": Array [], + "type": "index-pattern", + }, + Object { + "attributes": Object {}, + "id": "2", + "references": Array [ + Object { + "id": "1", + "name": "name", + "type": "index-pattern", + }, + ], + "type": "search", + }, + Object { + "excludedObjects": Array [], + "excludedObjectsCount": 0, + "exportedCount": 2, + "missingRefCount": 0, + "missingReferences": Array [], + }, + ] + `); expect(savedObjectsClient.bulkGet).toMatchInlineSnapshot(` [MockFunction] { "calls": Array [ @@ -1211,32 +1229,34 @@ describe('getSortedObjectsForExport()', () => { }); const response = await readStreamToCompletion(exportStream); expect(response).toMatchInlineSnapshot(` - Array [ - Object { - "attributes": Object {}, - "id": "1", - "references": Array [], - "type": "index-pattern", - }, - Object { - "attributes": Object {}, - "id": "2", - "references": Array [ - Object { - "id": "1", - "name": "name", - "type": "index-pattern", - }, - ], - "type": "search", - }, - Object { - "exportedCount": 2, - "missingRefCount": 0, - "missingReferences": Array [], - }, - ] - `); + Array [ + Object { + "attributes": Object {}, + "id": "1", + "references": Array [], + "type": "index-pattern", + }, + Object { + "attributes": Object {}, + "id": "2", + "references": Array [ + Object { + "id": "1", + "name": "name", + "type": "index-pattern", + }, + ], + "type": "search", + }, + Object { + "excludedObjects": Array [], + "excludedObjectsCount": 0, + "exportedCount": 2, + "missingRefCount": 0, + "missingReferences": Array [], + }, + ] + `); expect(savedObjectsClient.bulkGet).toMatchInlineSnapshot(` [MockFunction] { "calls": Array [ diff --git a/src/core/server/saved_objects/export/saved_objects_exporter.ts b/src/core/server/saved_objects/export/saved_objects_exporter.ts index 9d56bb4872a6dc..211dcdc4ee62d1 100644 --- a/src/core/server/saved_objects/export/saved_objects_exporter.ts +++ b/src/core/server/saved_objects/export/saved_objects_exporter.ts @@ -18,7 +18,6 @@ import { SavedObjectExportBaseOptions, SavedObjectsExportByObjectOptions, SavedObjectsExportByTypeOptions, - SavedObjectsExportTransform, } from './types'; import { SavedObjectsExportError } from './errors'; import { collectExportedObjects } from './collect_exported_objects'; @@ -34,8 +33,8 @@ export type ISavedObjectsExporter = PublicMethodsOf; */ export class SavedObjectsExporter { readonly #savedObjectsClient: SavedObjectsClientContract; - readonly #exportTransforms: Record; readonly #exportSizeLimit: number; + readonly #typeRegistry: ISavedObjectTypeRegistry; readonly #log: Logger; constructor({ @@ -52,15 +51,7 @@ export class SavedObjectsExporter { this.#log = logger; this.#savedObjectsClient = savedObjectsClient; this.#exportSizeLimit = exportSizeLimit; - this.#exportTransforms = typeRegistry.getAllTypes().reduce((transforms, type) => { - if (type.management?.onExport) { - return { - ...transforms, - [type.name]: type.management.onExport, - }; - } - return transforms; - }, {} as Record); + this.#typeRegistry = typeRegistry; } /** @@ -121,13 +112,15 @@ export class SavedObjectsExporter { const { objects: collectedObjects, missingRefs: missingReferences, + excludedObjects, } = await collectExportedObjects({ objects: savedObjects, includeReferences: includeReferencesDeep, namespace, request, - exportTransforms: this.#exportTransforms, + typeRegistry: this.#typeRegistry, savedObjectsClient: this.#savedObjectsClient, + logger: this.#log, }); // sort with the provided sort function then with the default export sorting @@ -142,6 +135,8 @@ export class SavedObjectsExporter { exportedCount: exportedObjects.length, missingRefCount: missingReferences.length, missingReferences, + excludedObjectsCount: excludedObjects.length, + excludedObjects, }; this.#log.debug(`Exporting [${redactedObjects.length}] saved objects.`); return createListStream([...redactedObjects, ...(excludeExportDetails ? [] : [exportDetails])]); diff --git a/src/core/server/saved_objects/export/types.ts b/src/core/server/saved_objects/export/types.ts index 7891af6df5b1b5..a805ec3a06c1b1 100644 --- a/src/core/server/saved_objects/export/types.ts +++ b/src/core/server/saved_objects/export/types.ts @@ -72,6 +72,20 @@ export interface SavedObjectsExportResultDetails { /** the missing reference type. */ type: string; }>; + /** number of objects that were excluded from the export */ + excludedObjectsCount: number; + /** excluded objects details */ + excludedObjects: SavedObjectsExportExcludedObject[]; +} + +/** @public */ +export interface SavedObjectsExportExcludedObject { + /** id of the excluded object */ + id: string; + /** type of the excluded object */ + type: string; + /** optional cause of the exclusion */ + reason?: string; } /** @@ -158,7 +172,7 @@ export interface SavedObjectsExportTransformContext { * * @public */ -export type SavedObjectsExportTransform = ( +export type SavedObjectsExportTransform = ( context: SavedObjectsExportTransformContext, objects: Array> ) => SavedObject[] | Promise; diff --git a/src/core/server/saved_objects/index.ts b/src/core/server/saved_objects/index.ts index b1b1584d7de88c..5f853d49219dc9 100644 --- a/src/core/server/saved_objects/index.ts +++ b/src/core/server/saved_objects/index.ts @@ -41,6 +41,7 @@ export type { SavedObjectsExportError, SavedObjectsExportTransformContext, SavedObjectsExportTransform, + SavedObjectsExportExcludedObject, } from './export'; export { SavedObjectsSerializer } from './serialization'; diff --git a/src/core/server/saved_objects/migrations/core/document_migrator.test.ts b/src/core/server/saved_objects/migrations/core/document_migrator.test.ts index 79f5bd09889db6..87b8ee08090641 100644 --- a/src/core/server/saved_objects/migrations/core/document_migrator.test.ts +++ b/src/core/server/saved_objects/migrations/core/document_migrator.test.ts @@ -748,7 +748,8 @@ describe('DocumentMigrator', () => { migrator.migrate(_.cloneDeep(failedDoc)); expect('Did not throw').toEqual('But it should have!'); } catch (error) { - expect(error.message).toBe('Dang diggity!'); + expect(error.message).toEqual('Migration function for version 1.2.3 threw an error'); + expect(error.stack.includes(`Caused by:\nError: Dang diggity!`)).toBe(true); expect(error).toBeInstanceOf(TransformSavedObjectDocumentError); } }); diff --git a/src/core/server/saved_objects/migrations/core/document_migrator.ts b/src/core/server/saved_objects/migrations/core/document_migrator.ts index a32cc999c55599..de8adc23996fd2 100644 --- a/src/core/server/saved_objects/migrations/core/document_migrator.ts +++ b/src/core/server/saved_objects/migrations/core/document_migrator.ts @@ -260,6 +260,7 @@ function validateMigrationsMapObject( throw new Error(`${prefix} Got ${obj}.`); } } + function assertValidSemver(version: string, type: string) { if (!Semver.valid(version)) { throw new Error( @@ -272,6 +273,7 @@ function validateMigrationsMapObject( ); } } + function assertValidTransform(fn: any, version: string, type: string) { if (typeof fn !== 'function') { throw new Error(`Invalid migration ${type}.${version}: expected a function, but got ${fn}.`); @@ -680,7 +682,7 @@ function wrapWithTry( return { transformedDoc: result, additionalDocs: [] }; } catch (error) { log.error(error); - throw new TransformSavedObjectDocumentError(error); + throw new TransformSavedObjectDocumentError(error, version); } }; } diff --git a/src/core/server/saved_objects/migrations/core/migrate_raw_docs.test.ts b/src/core/server/saved_objects/migrations/core/migrate_raw_docs.test.ts index 7a6f72a881cd6a..0481e6118acb0c 100644 --- a/src/core/server/saved_objects/migrations/core/migrate_raw_docs.test.ts +++ b/src/core/server/saved_objects/migrations/core/migrate_raw_docs.test.ts @@ -233,7 +233,7 @@ describe('migrateRawDocsSafely', () => { test('instance of Either.left containing transform errors when the transform function throws a TransformSavedObjectDocument error', async () => { const transform = jest.fn((doc: any) => { - throw new TransformSavedObjectDocumentError(new Error('error during transform')); + throw new TransformSavedObjectDocumentError(new Error('error during transform'), '8.0.0'); }); const task = migrateRawDocsSafely( new SavedObjectsSerializer(new SavedObjectTypeRegistry()), @@ -247,7 +247,7 @@ describe('migrateRawDocsSafely', () => { expect(result.left.transformErrors.length).toEqual(1); expect(result.left.transformErrors[0]).toMatchInlineSnapshot(` Object { - "err": [Error: error during transform], + "err": [Error: Migration function for version 8.0.0 threw an error], "rawId": "a:b", } `); diff --git a/src/core/server/saved_objects/migrations/core/transform_saved_object_document_error.test.ts b/src/core/server/saved_objects/migrations/core/transform_saved_object_document_error.test.ts index 1efb1bd726216a..66ee385b44f46f 100644 --- a/src/core/server/saved_objects/migrations/core/transform_saved_object_document_error.test.ts +++ b/src/core/server/saved_objects/migrations/core/transform_saved_object_document_error.test.ts @@ -10,10 +10,38 @@ import { TransformSavedObjectDocumentError } from './transform_saved_object_docu describe('TransformSavedObjectDocumentError', () => { it('is a special error', () => { const originalError = new Error('Dang diggity!'); - const err = new TransformSavedObjectDocumentError(originalError); + const err = new TransformSavedObjectDocumentError(originalError, '8.0.0'); + expect(err).toBeInstanceOf(TransformSavedObjectDocumentError); expect(err.stack).not.toBeNull(); expect(err.originalError).toBe(originalError); - expect(err.message).toMatchInlineSnapshot(`"Dang diggity!"`); + expect(err.message).toEqual(`Migration function for version 8.0.0 threw an error`); + }); + + it('adds the stack from the original error', () => { + const originalError = new Error('Some went wrong'); + originalError.stack = 'some stack trace'; + + const err = new TransformSavedObjectDocumentError(originalError, '8.0.0'); + const stackLines = err.stack!.split('\n'); + const stackLength = stackLines.length; + + expect(stackLength).toBeGreaterThan(3); + expect(stackLines[0]).toEqual(`Error: Migration function for version 8.0.0 threw an error`); + expect(stackLines[stackLength - 2]).toEqual(`Caused by:`); + expect(stackLines[stackLength - 1]).toEqual(`some stack trace`); + }); + + it('uses the message if the original error does not have a stack', () => { + const originalError = new Error('Some went wrong'); + delete originalError.stack; + + const err = new TransformSavedObjectDocumentError(originalError, '8.0.0'); + const stackLines = err.stack!.split('\n'); + const stackLength = stackLines.length; + + expect(stackLength).toBeGreaterThan(3); + expect(stackLines[stackLength - 2]).toEqual(`Caused by:`); + expect(stackLines[stackLength - 1]).toEqual(`Some went wrong`); }); }); diff --git a/src/core/server/saved_objects/migrations/core/transform_saved_object_document_error.ts b/src/core/server/saved_objects/migrations/core/transform_saved_object_document_error.ts index 2dc553545a08d6..11ad643687d85c 100644 --- a/src/core/server/saved_objects/migrations/core/transform_saved_object_document_error.ts +++ b/src/core/server/saved_objects/migrations/core/transform_saved_object_document_error.ts @@ -10,9 +10,13 @@ * Error thrown when saved object migrations encounter a transformation error. * Transformation errors happen when a transform function throws an error for an unsanitized saved object */ - export class TransformSavedObjectDocumentError extends Error { - constructor(public readonly originalError: Error) { - super(`${originalError.message}`); + constructor(public readonly originalError: Error, public readonly version: string) { + super(`Migration function for version ${version} threw an error`); + appendCauseStack(this, originalError); } } + +const appendCauseStack = (error: Error, cause: Error) => { + error.stack = (error.stack ?? '') + `\nCaused by:\n${cause.stack ?? cause.message}`; +}; diff --git a/src/core/server/saved_objects/migrationsv2/integration_tests/archives/8.0.0_document_migration_failure.zip b/src/core/server/saved_objects/migrationsv2/integration_tests/archives/8.0.0_document_migration_failure.zip new file mode 100644 index 00000000000000..9dc4de75c5d981 Binary files /dev/null and b/src/core/server/saved_objects/migrationsv2/integration_tests/archives/8.0.0_document_migration_failure.zip differ diff --git a/src/core/server/saved_objects/migrationsv2/integration_tests/cleanup.test.ts b/src/core/server/saved_objects/migrationsv2/integration_tests/cleanup.test.ts index 83d97555a47987..3bbdc27e1dd2f6 100644 --- a/src/core/server/saved_objects/migrationsv2/integration_tests/cleanup.test.ts +++ b/src/core/server/saved_objects/migrationsv2/integration_tests/cleanup.test.ts @@ -17,6 +17,7 @@ const logFilePath = Path.join(__dirname, 'cleanup_test.log'); const asyncUnlink = Util.promisify(Fs.unlink); const asyncReadFile = Util.promisify(Fs.readFile); + async function removeLogFile() { // ignore errors if it doesn't exist await asyncUnlink(logFilePath).catch(() => void 0); @@ -99,9 +100,10 @@ describe('migration v2', () => { esServer = await startES(); await root.setup(); - await expect(root.start()).rejects.toThrow( - 'Unable to complete saved object migrations for the [.kibana] index: Migrations failed. Reason: Corrupt saved object documents: index-pattern:test_index*. To allow migrations to proceed, please delete these documents.' - ); + await expect(root.start()).rejects.toThrowErrorMatchingInlineSnapshot(` + "Unable to complete saved object migrations for the [.kibana] index: Migrations failed. Reason: 1 corrupt saved object documents were found: index-pattern:test_index* + To allow migrations to proceed, please delete or fix these documents." + `); const logFileContent = await asyncReadFile(logFilePath, 'utf-8'); const records = logFileContent diff --git a/src/core/server/saved_objects/migrationsv2/integration_tests/corrupt_outdated_docs.test.ts b/src/core/server/saved_objects/migrationsv2/integration_tests/corrupt_outdated_docs.test.ts index 9a09fb47d06097..7561536b1ed4b9 100644 --- a/src/core/server/saved_objects/migrationsv2/integration_tests/corrupt_outdated_docs.test.ts +++ b/src/core/server/saved_objects/migrationsv2/integration_tests/corrupt_outdated_docs.test.ts @@ -15,6 +15,7 @@ import { Root } from '../../../root'; const logFilePath = Path.join(__dirname, 'migration_test_corrupt_docs_kibana.log'); const asyncUnlink = Util.promisify(Fs.unlink); + async function removeLogFile() { // ignore errors if it doesn't exist await asyncUnlink(logFilePath).catch(() => void 0); @@ -110,11 +111,13 @@ describe('migration v2 with corrupt saved object documents', () => { const errorMessage = err.message; expect( errorMessage.startsWith( - 'Unable to complete saved object migrations for the [.kibana] index: Migrations failed. Reason: Corrupt saved object documents: ' + 'Unable to complete saved object migrations for the [.kibana] index: Migrations failed. Reason: 19 corrupt saved object documents were found: ' ) ).toBeTruthy(); expect( - errorMessage.endsWith(' To allow migrations to proceed, please delete these documents.') + errorMessage.endsWith( + 'To allow migrations to proceed, please delete or fix these documents.' + ) ).toBeTruthy(); const expectedCorruptDocIds = [ '"foo:my_name"', diff --git a/src/core/server/saved_objects/migrationsv2/integration_tests/migration_7_13_0_transform_failures.test.ts b/src/core/server/saved_objects/migrationsv2/integration_tests/migration_7_13_0_transform_failures.test.ts index c014f7de395e04..73c7016d32c563 100644 --- a/src/core/server/saved_objects/migrationsv2/integration_tests/migration_7_13_0_transform_failures.test.ts +++ b/src/core/server/saved_objects/migrationsv2/integration_tests/migration_7_13_0_transform_failures.test.ts @@ -15,6 +15,7 @@ import { Root } from '../../../root'; const logFilePath = Path.join(__dirname, '7_13_corrupt_transform_failures_test.log'); const asyncUnlink = Util.promisify(Fs.unlink); + async function removeLogFile() { // ignore errors if it doesn't exist await asyncUnlink(logFilePath).catch(() => void 0); @@ -98,11 +99,13 @@ describe('migration v2', () => { const errorMessage = err.message; expect( errorMessage.startsWith( - 'Unable to complete saved object migrations for the [.kibana] index: Migrations failed. Reason: Corrupt saved object documents: ' + 'Unable to complete saved object migrations for the [.kibana] index: Migrations failed. Reason: 7 corrupt saved object documents were found: ' ) ).toBeTruthy(); expect( - errorMessage.endsWith(' To allow migrations to proceed, please delete these documents.') + errorMessage.endsWith( + 'To allow migrations to proceed, please delete or fix these documents.' + ) ).toBeTruthy(); const expectedCorruptDocIds = [ @@ -117,9 +120,13 @@ describe('migration v2', () => { for (const corruptDocId of expectedCorruptDocIds) { expect(errorMessage.includes(corruptDocId)).toBeTruthy(); } - const expectedTransformErrorMessage = - 'Transformation errors: space:default: Document "default" has property "space" which belongs to a more recent version of Kibana [6.6.0]. The last known version is [undefined]'; - expect(errorMessage.includes(expectedTransformErrorMessage)).toBeTruthy(); + + expect(errorMessage.includes('7 transformation errors were encountered:')).toBeTruthy(); + expect( + errorMessage.includes( + 'space:default: Error: Document "default" has property "space" which belongs to a more recent version of Kibana [6.6.0]. The last known version is [undefined]' + ) + ).toBeTruthy(); } }); }); diff --git a/src/core/server/saved_objects/migrationsv2/integration_tests/type_migration_failure.test.ts b/src/core/server/saved_objects/migrationsv2/integration_tests/type_migration_failure.test.ts new file mode 100644 index 00000000000000..ac40933d2a7dea --- /dev/null +++ b/src/core/server/saved_objects/migrationsv2/integration_tests/type_migration_failure.test.ts @@ -0,0 +1,201 @@ +/* + * 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 Path from 'path'; +import Fs from 'fs'; +import Util from 'util'; +import * as kbnTestServer from '../../../../test_helpers/kbn_server'; +import { Root } from '../../../root'; + +const logFilePath = Path.join(__dirname, 'migration_test_corrupt_docs_kibana.log'); + +const asyncUnlink = Util.promisify(Fs.unlink); + +async function removeLogFile() { + // ignore errors if it doesn't exist + await asyncUnlink(logFilePath).catch(() => void 0); +} + +describe('migration v2 with corrupt saved object documents', () => { + let esServer: kbnTestServer.TestElasticsearchUtils; + let root: Root; + + beforeAll(async () => { + await removeLogFile(); + }); + + afterAll(async () => { + if (root) { + await root.shutdown(); + } + if (esServer) { + await esServer.stop(); + } + + await new Promise((resolve) => setTimeout(resolve, 10000)); + }); + + it('collects corrupt saved object documents accross batches', async () => { + const { startES } = kbnTestServer.createTestServers({ + adjustTimeout: (t: number) => jest.setTimeout(t), + settings: { + es: { + license: 'basic', + // contains 4 `foo` objects, all with a `migrationVersion` of `7.13.0` + // - foo:1 and foo:2 have correct values for their `number` property (13 and 42 respectively) + // - foo:3 and foo:4 don't have the property, and will fail during the `7.14.0` registered migration + // contains migrated index with 8.0 aliases to skip migration, but run outdated doc search + dataArchive: Path.join(__dirname, 'archives', '8.0.0_document_migration_failure.zip'), + }, + }, + }); + + root = createRoot(); + + esServer = await startES(); + const coreSetup = await root.setup(); + + coreSetup.savedObjects.registerType({ + name: 'foo', + hidden: false, + mappings: { + properties: { + number: { type: 'integer' }, + }, + }, + namespaceType: 'agnostic', + migrations: { + '7.14.0': (doc) => { + if (doc.attributes.number === undefined) { + throw new Error('"number" attribute should be present'); + } + doc.attributes = { + ...doc.attributes, + number: doc.attributes.number + 9000, + }; + return doc; + }, + }, + }); + + try { + await root.start(); + expect(true).toEqual(false); + } catch (err) { + const errorMessage = err.message; + const errorLines = errorMessage.split('\n'); + + expect(errorLines[0]).toEqual( + `Unable to complete saved object migrations for the [.kibana] index: Migrations failed. Reason: 2 transformation errors were encountered:` + ); + expect(errorLines[errorLines.length - 1]).toEqual( + `To allow migrations to proceed, please delete or fix these documents.` + ); + + expectMatchOrder(errorLines, [ + { + mode: 'equal', + value: '- foo:3: Error: Migration function for version 7.14.0 threw an error', + }, + { + mode: 'contain', + value: 'at transform', + }, + { + mode: 'equal', + value: 'Caused by:', + }, + { + mode: 'equal', + value: 'Error: "number" attribute should be present', + }, + { + mode: 'contain', + value: 'at migrationFn', + }, + { + mode: 'equal', + value: '- foo:4: Error: Migration function for version 7.14.0 threw an error', + }, + { + mode: 'contain', + value: 'at transform', + }, + { + mode: 'equal', + value: 'Caused by:', + }, + { + mode: 'equal', + value: 'Error: "number" attribute should be present', + }, + { + mode: 'contain', + value: 'at migrationFn', + }, + ]); + } + }); +}); + +function createRoot() { + return kbnTestServer.createRootWithCorePlugins( + { + migrations: { + skip: false, + enableV2: true, + batchSize: 5, + }, + logging: { + appenders: { + file: { + type: 'file', + fileName: logFilePath, + layout: { + type: 'json', + }, + }, + }, + loggers: [ + { + name: 'root', + appenders: ['file'], + }, + ], + }, + }, + { + oss: true, + } + ); +} + +type FindInOrderPattern = { mode: 'equal'; value: string } | { mode: 'contain'; value: string }; + +const expectMatchOrder = (lines: string[], patterns: FindInOrderPattern[]) => { + let lineIdx = 0; + let patternIdx = 0; + + while (lineIdx < lines.length && patternIdx < patterns.length) { + const line = lines[lineIdx]; + const pattern = patterns[patternIdx]; + if (lineMatch(line, pattern)) { + patternIdx++; + } + lineIdx++; + } + + expect(patternIdx).toEqual(patterns.length); +}; + +const lineMatch = (line: string, pattern: FindInOrderPattern) => { + if (pattern.mode === 'contain') { + return line.trim().includes(pattern.value.trim()); + } + return line.trim() === pattern.value.trim(); +}; diff --git a/src/core/server/saved_objects/migrationsv2/model.test.ts b/src/core/server/saved_objects/migrationsv2/model.test.ts index 86dc590aabdad8..ea8bc7f1107352 100644 --- a/src/core/server/saved_objects/migrationsv2/model.test.ts +++ b/src/core/server/saved_objects/migrationsv2/model.test.ts @@ -863,9 +863,10 @@ describe('migrations v2 model', () => { }); const newState = model(testState, res) as FatalState; expect(newState.controlState).toBe('FATAL'); - expect(newState.reason).toMatchInlineSnapshot( - `"Migrations failed. Reason: Corrupt saved object documents: a:b. To allow migrations to proceed, please delete these documents."` - ); + expect(newState.reason).toMatchInlineSnapshot(` + "Migrations failed. Reason: 1 corrupt saved object documents were found: a:b + To allow migrations to proceed, please delete or fix these documents." + `); expect(newState.logs).toStrictEqual([]); // No logs because no hits }); }); @@ -1158,7 +1159,10 @@ describe('migrations v2 model', () => { it('OUTDATED_DOCUMENTS_SEARCH_READ -> FATAL if no outdated documents to transform and we have failed document migrations', () => { const corruptDocumentIdsCarriedOver = ['a:somethingelse']; const originalTransformError = new Error('something went wrong'); - const transFormErr = new TransformSavedObjectDocumentError(originalTransformError); + const transFormErr = new TransformSavedObjectDocumentError( + originalTransformError, + '7.11.0' + ); const transformationErrors = [ { rawId: 'bob:tail', err: transFormErr }, ] as TransformErrorObjects[]; @@ -1175,8 +1179,8 @@ describe('migrations v2 model', () => { const newState = model(transformErrorsState, res) as FatalState; expect(newState.controlState).toBe('FATAL'); expect(newState.reason.includes('Migrations failed. Reason:')).toBe(true); - expect(newState.reason.includes('Corrupt saved object documents: ')).toBe(true); - expect(newState.reason.includes('Transformation errors: ')).toBe(true); + expect(newState.reason.includes('1 corrupt saved object documents were found')).toBe(true); + expect(newState.reason.includes('1 transformation errors were encountered')).toBe(true); expect(newState.reason.includes('bob:tail')).toBe(true); expect(newState.logs).toStrictEqual([]); // No logs because no hits }); @@ -1222,7 +1226,7 @@ describe('migrations v2 model', () => { const outdatedDocuments = [{ _id: '1', _source: { type: 'vis' } }]; const corruptDocumentIds = ['a:somethingelse']; const originalTransformError = new Error('Dang diggity!'); - const transFormErr = new TransformSavedObjectDocumentError(originalTransformError); + const transFormErr = new TransformSavedObjectDocumentError(originalTransformError, '7.11.0'); const transformationErrors = [ { rawId: 'bob:tail', err: transFormErr }, ] as TransformErrorObjects[]; diff --git a/src/core/server/saved_objects/migrationsv2/model.ts b/src/core/server/saved_objects/migrationsv2/model.ts index 252d7424c339cc..6aa119af2f6c87 100644 --- a/src/core/server/saved_objects/migrationsv2/model.ts +++ b/src/core/server/saved_objects/migrationsv2/model.ts @@ -112,17 +112,22 @@ function extractTransformFailuresReason( ): string { const corruptDocumentIdReason = corruptDocumentIds.length > 0 - ? ` Corrupt saved object documents: ${corruptDocumentIds.join(',')}` + ? ` ${ + corruptDocumentIds.length + } corrupt saved object documents were found: ${corruptDocumentIds.join(',')}` : ''; // we have both the saved object Id and the stack trace in each `transformErrors` item. const transformErrorsReason = transformErrors.length > 0 - ? ' Transformation errors: ' + + ? ` ${transformErrors.length} transformation errors were encountered:\n ` + transformErrors - .map((errObj) => `${errObj.rawId}: ${errObj.err.message}\n ${errObj.err.stack ?? ''}`) - .join('/n') + .map((errObj) => `- ${errObj.rawId}: ${errObj.err.stack ?? errObj.err.message}\n`) + .join('') : ''; - return `Migrations failed. Reason:${corruptDocumentIdReason}${transformErrorsReason}. To allow migrations to proceed, please delete these documents.`; + return ( + `Migrations failed. Reason:${corruptDocumentIdReason}${transformErrorsReason}\n` + + `To allow migrations to proceed, please delete or fix these documents.` + ); } const delayRetryState = ( diff --git a/src/core/server/saved_objects/saved_objects_service.ts b/src/core/server/saved_objects/saved_objects_service.ts index b95f187cd44caa..e50c1e540bfaf4 100644 --- a/src/core/server/saved_objects/saved_objects_service.ts +++ b/src/core/server/saved_objects/saved_objects_service.ts @@ -141,7 +141,7 @@ export interface SavedObjectsServiceSetup { * } * ``` */ - registerType: (type: SavedObjectsType) => void; + registerType: (type: SavedObjectsType) => void; } /** diff --git a/src/core/server/saved_objects/types.ts b/src/core/server/saved_objects/types.ts index 964ba671b59646..1bb214de701e28 100644 --- a/src/core/server/saved_objects/types.ts +++ b/src/core/server/saved_objects/types.ts @@ -253,7 +253,7 @@ export type SavedObjectsNamespaceType = 'single' | 'multiple' | 'multiple-isolat * * @public */ -export interface SavedObjectsType { +export interface SavedObjectsType { /** * The name of the type, which is also used as the internal id. */ @@ -337,7 +337,7 @@ export interface SavedObjectsType { /** * An optional {@link SavedObjectsTypeManagementDefinition | saved objects management section} definition for the type. */ - management?: SavedObjectsTypeManagementDefinition; + management?: SavedObjectsTypeManagementDefinition; } /** @@ -345,7 +345,7 @@ export interface SavedObjectsType { * * @public */ -export interface SavedObjectsTypeManagementDefinition { +export interface SavedObjectsTypeManagementDefinition { /** * Is the type importable or exportable. Defaults to `false`. */ @@ -363,12 +363,12 @@ export interface SavedObjectsTypeManagementDefinition { * Function returning the title to display in the management table. * If not defined, will use the object's type and id to generate a label. */ - getTitle?: (savedObject: SavedObject) => string; + getTitle?: (savedObject: SavedObject) => string; /** * Function returning the url to use to redirect to the editing page of this object. * If not defined, editing will not be allowed. */ - getEditUrl?: (savedObject: SavedObject) => string; + getEditUrl?: (savedObject: SavedObject) => string; /** * Function returning the url to use to redirect to this object from the management section. * If not defined, redirecting to the object will not be allowed. @@ -377,7 +377,9 @@ export interface SavedObjectsTypeManagementDefinition { * the object page, relative to the base path. `uiCapabilitiesPath` is the path to check in the * {@link Capabilities | uiCapabilities} to check if the user has permission to access the object. */ - getInAppUrl?: (savedObject: SavedObject) => { path: string; uiCapabilitiesPath: string }; + getInAppUrl?: ( + savedObject: SavedObject + ) => { path: string; uiCapabilitiesPath: string }; /** * An optional export transform function that can be used transform the objects of the registered type during * the export process. @@ -386,9 +388,14 @@ export interface SavedObjectsTypeManagementDefinition { * * See {@link SavedObjectsExportTransform | the transform type documentation} for more info and examples. * + * When implementing both `isExportable` and `onExport`, it is mandatory that + * `isExportable` returns the same value for an object before and after going + * though the export transform. + * E.g `isExportable(objectBeforeTransform) === isExportable(objectAfterTransform)` + * * @remarks `importableAndExportable` must be `true` to specify this property. */ - onExport?: SavedObjectsExportTransform; + onExport?: SavedObjectsExportTransform; /** * An optional {@link SavedObjectsImportHook | import hook} to use when importing given type. * @@ -431,5 +438,52 @@ export interface SavedObjectsTypeManagementDefinition { * @remarks messages returned in the warnings are user facing and must be translated. * @remarks `importableAndExportable` must be `true` to specify this property. */ - onImport?: SavedObjectsImportHook; + onImport?: SavedObjectsImportHook; + + /** + * Optional hook to specify whether an object should be exportable. + * + * If specified, `isExportable` will be called during export for each + * of this type's objects in the export, and the ones not matching the + * predicate will be excluded from the export. + * + * When implementing both `isExportable` and `onExport`, it is mandatory that + * `isExportable` returns the same value for an object before and after going + * though the export transform. + * E.g `isExportable(objectBeforeTransform) === isExportable(objectAfterTransform)` + * + * @example + * Registering a type with a per-object exportability predicate + * ```ts + * // src/plugins/my_plugin/server/plugin.ts + * import { myType } from './saved_objects'; + * + * export class Plugin() { + * setup: (core: CoreSetup) => { + * core.savedObjects.registerType({ + * ...myType, + * management: { + * ...myType.management, + * isExportable: (object) => { + * if (object.attributes.myCustomAttr === 'foo') { + * return false; + * } + * return true; + * } + * }, + * }); + * } + * } + * ``` + * + * @remarks `importableAndExportable` must be `true` to specify this property. + */ + isExportable?: SavedObjectsExportablePredicate; } + +/** + * @public + */ +export type SavedObjectsExportablePredicate = ( + obj: SavedObject +) => boolean; diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index ce13174ee19cc2..9e7721fde90e7d 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -2508,8 +2508,17 @@ export class SavedObjectsExportError extends Error { readonly type: string; } +// @public (undocumented) +export interface SavedObjectsExportExcludedObject { + id: string; + reason?: string; + type: string; +} + // @public export interface SavedObjectsExportResultDetails { + excludedObjects: SavedObjectsExportExcludedObject[]; + excludedObjectsCount: number; exportedCount: number; missingRefCount: number; missingReferences: Array<{ @@ -2519,7 +2528,7 @@ export interface SavedObjectsExportResultDetails { } // @public -export type SavedObjectsExportTransform = (context: SavedObjectsExportTransformContext, objects: Array>) => SavedObject[] | Promise; +export type SavedObjectsExportTransform = (context: SavedObjectsExportTransformContext, objects: Array>) => SavedObject[] | Promise; // @public export interface SavedObjectsExportTransformContext { @@ -2930,7 +2939,7 @@ export class SavedObjectsSerializer { // @public export interface SavedObjectsServiceSetup { addClientWrapper: (priority: number, id: string, factory: SavedObjectsClientWrapperFactory) => void; - registerType: (type: SavedObjectsType) => void; + registerType: (type: SavedObjectsType) => void; setClientFactoryProvider: (clientFactoryProvider: SavedObjectsClientFactoryProvider) => void; } @@ -2956,12 +2965,12 @@ export interface SavedObjectStatusMeta { } // @public (undocumented) -export interface SavedObjectsType { +export interface SavedObjectsType { convertToAliasScript?: string; convertToMultiNamespaceTypeVersion?: string; hidden: boolean; indexPattern?: string; - management?: SavedObjectsTypeManagementDefinition; + management?: SavedObjectsTypeManagementDefinition; mappings: SavedObjectsTypeMappingDefinition; migrations?: SavedObjectMigrationMap | (() => SavedObjectMigrationMap); name: string; @@ -2969,18 +2978,20 @@ export interface SavedObjectsType { } // @public -export interface SavedObjectsTypeManagementDefinition { +export interface SavedObjectsTypeManagementDefinition { defaultSearchField?: string; - getEditUrl?: (savedObject: SavedObject) => string; - getInAppUrl?: (savedObject: SavedObject) => { + getEditUrl?: (savedObject: SavedObject) => string; + getInAppUrl?: (savedObject: SavedObject) => { path: string; uiCapabilitiesPath: string; }; - getTitle?: (savedObject: SavedObject) => string; + getTitle?: (savedObject: SavedObject) => string; icon?: string; importableAndExportable?: boolean; - onExport?: SavedObjectsExportTransform; - onImport?: SavedObjectsImportHook; + // Warning: (ae-forgotten-export) The symbol "SavedObjectsExportablePredicate" needs to be exported by the entry point index.d.ts + isExportable?: SavedObjectsExportablePredicate; + onExport?: SavedObjectsExportTransform; + onImport?: SavedObjectsImportHook; } // @public @@ -3045,11 +3056,11 @@ export class SavedObjectsUtils { // @public export class SavedObjectTypeRegistry { - getAllTypes(): SavedObjectsType[]; - getImportableAndExportableTypes(): SavedObjectsType[]; + getAllTypes(): SavedObjectsType[]; + getImportableAndExportableTypes(): SavedObjectsType[]; getIndex(type: string): string | undefined; - getType(type: string): SavedObjectsType | undefined; - getVisibleTypes(): SavedObjectsType[]; + getType(type: string): SavedObjectsType | undefined; + getVisibleTypes(): SavedObjectsType[]; isHidden(type: string): boolean; isImportableAndExportable(type: string): boolean; isMultiNamespace(type: string): boolean; diff --git a/typings/elasticsearch/index.d.ts b/src/core/types/elasticsearch/index.ts similarity index 94% rename from typings/elasticsearch/index.d.ts rename to src/core/types/elasticsearch/index.ts index 1951434890c50f..bec611778e6f56 100644 --- a/typings/elasticsearch/index.d.ts +++ b/src/core/types/elasticsearch/index.ts @@ -29,4 +29,4 @@ export type ESSearchResponse< TOptions extends { restTotalHitsAsInt: boolean } = { restTotalHitsAsInt: false } > = InferSearchResponseOf; -export { InferSearchResponseOf, AggregationResultOf, SearchHit }; +export type { InferSearchResponseOf, AggregationResultOf, SearchHit }; diff --git a/typings/elasticsearch/search.d.ts b/src/core/types/elasticsearch/search.ts similarity index 100% rename from typings/elasticsearch/search.d.ts rename to src/core/types/elasticsearch/search.ts diff --git a/src/plugins/dashboard/public/plugin.tsx b/src/plugins/dashboard/public/plugin.tsx index b73fe5f2ba410d..b5d6eda71ca4a2 100644 --- a/src/plugins/dashboard/public/plugin.tsx +++ b/src/plugins/dashboard/public/plugin.tsx @@ -205,19 +205,6 @@ export class DashboardPlugin }; }; - if (share) { - this.dashboardUrlGenerator = share.urlGenerators.registerUrlGenerator( - createDashboardUrlGenerator(async () => { - const [coreStart, , selfStart] = await core.getStartServices(); - return { - appBasePath: coreStart.application.getUrlForApp('dashboards'), - useHashedUrl: coreStart.uiSettings.get('state:storeInSessionStorage'), - savedDashboardLoader: selfStart.getSavedDashboardLoader(), - }; - }) - ); - } - const { appMounted, appUnMounted, diff --git a/src/plugins/kibana_react/public/code_editor/index.tsx b/src/plugins/kibana_react/public/code_editor/index.tsx index 2440974c3b1d1e..9e3824b7842197 100644 --- a/src/plugins/kibana_react/public/code_editor/index.tsx +++ b/src/plugins/kibana_react/public/code_editor/index.tsx @@ -17,6 +17,9 @@ import darkTheme from '@elastic/eui/dist/eui_theme_dark.json'; import lightTheme from '@elastic/eui/dist/eui_theme_light.json'; import { useUiSetting } from '../ui_settings'; import { Props } from './code_editor'; +import './register_languages'; + +export * from './languages'; const LazyBaseEditor = React.lazy(() => import('./code_editor')); diff --git a/src/plugins/kibana_react/public/url_template_editor/constants.ts b/src/plugins/kibana_react/public/code_editor/languages/css/constants.ts similarity index 90% rename from src/plugins/kibana_react/public/url_template_editor/constants.ts rename to src/plugins/kibana_react/public/code_editor/languages/css/constants.ts index 6c1a1dbce5d674..2f465775e2a1b5 100644 --- a/src/plugins/kibana_react/public/url_template_editor/constants.ts +++ b/src/plugins/kibana_react/public/code_editor/languages/css/constants.ts @@ -6,4 +6,4 @@ * Side Public License, v 1. */ -export const LANG = 'handlebars_url'; +export const LANG = 'css'; diff --git a/src/plugins/kibana_react/public/code_editor/languages/css/index.ts b/src/plugins/kibana_react/public/code_editor/languages/css/index.ts new file mode 100644 index 00000000000000..fa1cbf4808a4eb --- /dev/null +++ b/src/plugins/kibana_react/public/code_editor/languages/css/index.ts @@ -0,0 +1,12 @@ +/* + * 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 { LangModuleType } from '@kbn/monaco'; +import { lexerRules, languageConfiguration } from './language'; +import { LANG } from './constants'; + +export const Lang: LangModuleType = { ID: LANG, lexerRules, languageConfiguration }; diff --git a/src/plugins/kibana_react/public/code_editor/languages/css/language.ts b/src/plugins/kibana_react/public/code_editor/languages/css/language.ts new file mode 100644 index 00000000000000..5bdd6c8eb8b1f7 --- /dev/null +++ b/src/plugins/kibana_react/public/code_editor/languages/css/language.ts @@ -0,0 +1,12 @@ +/* + * 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. + */ + +/* eslint-disable @kbn/eslint/module_migration */ +import { conf, language } from 'monaco-editor/esm/vs/basic-languages/css/css'; + +export { conf as languageConfiguration, language as lexerRules }; diff --git a/src/plugins/kibana_react/public/code_editor/languages/handlebars/constants.ts b/src/plugins/kibana_react/public/code_editor/languages/handlebars/constants.ts new file mode 100644 index 00000000000000..1634c02429f596 --- /dev/null +++ b/src/plugins/kibana_react/public/code_editor/languages/handlebars/constants.ts @@ -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 const LANG = 'handlebars'; diff --git a/src/plugins/kibana_react/public/code_editor/languages/handlebars/index.ts b/src/plugins/kibana_react/public/code_editor/languages/handlebars/index.ts new file mode 100644 index 00000000000000..ff3c08267da9bb --- /dev/null +++ b/src/plugins/kibana_react/public/code_editor/languages/handlebars/index.ts @@ -0,0 +1,13 @@ +/* + * 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 { LangModuleType } from '@kbn/monaco'; +import { languageConfiguration, lexerRules } from './language'; +import { LANG } from './constants'; + +export const Lang: LangModuleType = { ID: LANG, languageConfiguration, lexerRules }; diff --git a/src/plugins/kibana_react/public/url_template_editor/language.ts b/src/plugins/kibana_react/public/code_editor/languages/handlebars/language.ts similarity index 96% rename from src/plugins/kibana_react/public/url_template_editor/language.ts rename to src/plugins/kibana_react/public/code_editor/languages/handlebars/language.ts index 278a7130ad1fa6..7f760836088d60 100644 --- a/src/plugins/kibana_react/public/url_template_editor/language.ts +++ b/src/plugins/kibana_react/public/code_editor/languages/handlebars/language.ts @@ -13,7 +13,7 @@ import { monaco } from '@kbn/monaco'; -export const conf: monaco.languages.LanguageConfiguration = { +export const languageConfiguration: monaco.languages.LanguageConfiguration = { wordPattern: /(-?\d*\.\d\w*)|([^\`\~\!\@\$\^\&\*\(\)\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\s]+)/g, comments: { @@ -42,7 +42,7 @@ export const conf: monaco.languages.LanguageConfiguration = { ], }; -export const language: monaco.languages.IMonarchLanguage = { +export const lexerRules: monaco.languages.IMonarchLanguage = { // Set defaultToken to invalid to see what you do not tokenize yet. defaultToken: 'invalid', tokenPostfix: '', diff --git a/src/plugins/kibana_react/public/code_editor/languages/index.ts b/src/plugins/kibana_react/public/code_editor/languages/index.ts new file mode 100644 index 00000000000000..ff7da1725fa7f9 --- /dev/null +++ b/src/plugins/kibana_react/public/code_editor/languages/index.ts @@ -0,0 +1,13 @@ +/* + * 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 { Lang as CssLang } from './css'; +import { Lang as HandlebarsLang } from './handlebars'; +import { Lang as MarkdownLang } from './markdown'; + +export { CssLang, HandlebarsLang, MarkdownLang }; diff --git a/src/plugins/kibana_react/public/code_editor/languages/markdown/constants.ts b/src/plugins/kibana_react/public/code_editor/languages/markdown/constants.ts new file mode 100644 index 00000000000000..bd8aa23256637e --- /dev/null +++ b/src/plugins/kibana_react/public/code_editor/languages/markdown/constants.ts @@ -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 const LANG = 'markdown'; diff --git a/src/plugins/kibana_react/public/code_editor/languages/markdown/index.ts b/src/plugins/kibana_react/public/code_editor/languages/markdown/index.ts new file mode 100644 index 00000000000000..f501de74debec9 --- /dev/null +++ b/src/plugins/kibana_react/public/code_editor/languages/markdown/index.ts @@ -0,0 +1,12 @@ +/* + * 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 { LangModuleType } from '@kbn/monaco'; +import { languageConfiguration, lexerRules } from './language'; +import { LANG } from './constants'; + +export const Lang: LangModuleType = { ID: LANG, languageConfiguration, lexerRules }; diff --git a/src/plugins/kibana_react/public/code_editor/languages/markdown/language.ts b/src/plugins/kibana_react/public/code_editor/languages/markdown/language.ts new file mode 100644 index 00000000000000..d8a1234fcf191b --- /dev/null +++ b/src/plugins/kibana_react/public/code_editor/languages/markdown/language.ts @@ -0,0 +1,12 @@ +/* + * 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. + */ + +/* eslint-disable @kbn/eslint/module_migration */ +import { conf, language } from 'monaco-editor/esm/vs/basic-languages/markdown/markdown'; + +export { conf as languageConfiguration, language as lexerRules }; diff --git a/src/plugins/kibana_react/public/code_editor/register_languages.ts b/src/plugins/kibana_react/public/code_editor/register_languages.ts new file mode 100644 index 00000000000000..b4a0f4d53cdf47 --- /dev/null +++ b/src/plugins/kibana_react/public/code_editor/register_languages.ts @@ -0,0 +1,13 @@ +/* + * 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 { registerLanguage } from '@kbn/monaco'; +import { CssLang, HandlebarsLang, MarkdownLang } from './languages'; + +registerLanguage(CssLang); +registerLanguage(HandlebarsLang); +registerLanguage(MarkdownLang); diff --git a/src/plugins/kibana_react/public/url_template_editor/url_template_editor.tsx b/src/plugins/kibana_react/public/url_template_editor/url_template_editor.tsx index f830b4012976ae..0fed4d37e4f7f6 100644 --- a/src/plugins/kibana_react/public/url_template_editor/url_template_editor.tsx +++ b/src/plugins/kibana_react/public/url_template_editor/url_template_editor.tsx @@ -9,18 +9,10 @@ import * as React from 'react'; import { monaco } from '@kbn/monaco'; import { Props as CodeEditorProps } from '../code_editor/code_editor'; -import { CodeEditor } from '../code_editor'; -import { LANG } from './constants'; -import { language, conf } from './language'; +import { CodeEditor, HandlebarsLang } from '../code_editor'; import './styles.scss'; -monaco.languages.register({ - id: LANG, -}); -monaco.languages.setMonarchTokensProvider(LANG, language); -monaco.languages.setLanguageConfiguration(LANG, conf); - export interface UrlTemplateEditorVariable { label: string; title?: string; @@ -74,7 +66,7 @@ export const UrlTemplateEditor: React.FC = ({ return; } - const { dispose } = monaco.languages.registerCompletionItemProvider(LANG, { + const { dispose } = monaco.languages.registerCompletionItemProvider(HandlebarsLang.ID, { triggerCharacters: ['{', '/', '?', '&', '='], provideCompletionItems(model, position, context, token) { const { lineNumber } = position; @@ -132,7 +124,7 @@ export const UrlTemplateEditor: React.FC = ({ return (
{ }; const detailsLine = ( exported: number, - missingRefs: SavedObjectsExportResultDetails['missingReferences'] = [] + { + missingRefs = [], + excludedObjects = [], + }: { + missingRefs?: SavedObjectsExportResultDetails['missingReferences']; + excludedObjects?: SavedObjectsExportResultDetails['excludedObjects']; + } = {} ) => { return ( JSON.stringify({ exportedCount: exported, missingRefCount: missingRefs.length, missingReferences: missingRefs, - }) + '\n' + excludedObjectsCount: excludedObjects.length, + excludedObjects, + } as SavedObjectsExportResultDetails) + '\n' ); }; @@ -43,6 +51,8 @@ describe('extractExportDetails', () => { exportedCount: 3, missingRefCount: 0, missingReferences: [], + excludedObjectsCount: 0, + excludedObjects: [], }); }); @@ -51,10 +61,12 @@ describe('extractExportDetails', () => { [ [ objLine('1', 'index-pattern'), - detailsLine(1, [ - { id: '2', type: 'index-pattern' }, - { id: '3', type: 'index-pattern' }, - ]), + detailsLine(1, { + missingRefs: [ + { id: '2', type: 'index-pattern' }, + { id: '3', type: 'index-pattern' }, + ], + }), ].join(''), ], { @@ -71,6 +83,39 @@ describe('extractExportDetails', () => { { id: '2', type: 'index-pattern' }, { id: '3', type: 'index-pattern' }, ], + excludedObjectsCount: 0, + excludedObjects: [], + }); + }); + + it('should properly extract the excluded objects', async () => { + const exportData = new Blob( + [ + [ + objLine('1', 'index-pattern'), + detailsLine(1, { + excludedObjects: [ + { id: '2', type: 'index-pattern', reason: 'foo' }, + { id: '3', type: 'index-pattern' }, + ], + }), + ].join(''), + ], + { + type: 'application/ndjson', + endings: 'transparent', + } + ); + const result = await extractExportDetails(exportData); + expect(result).toEqual({ + exportedCount: 1, + missingRefCount: 0, + missingReferences: [], + excludedObjectsCount: 2, + excludedObjects: [ + { id: '2', type: 'index-pattern', reason: 'foo' }, + { id: '3', type: 'index-pattern' }, + ], }); }); diff --git a/src/plugins/saved_objects_management/public/lib/extract_export_details.ts b/src/plugins/saved_objects_management/public/lib/extract_export_details.ts index 40f8039a8cdae5..4d142330dca881 100644 --- a/src/plugins/saved_objects_management/public/lib/extract_export_details.ts +++ b/src/plugins/saved_objects_management/public/lib/extract_export_details.ts @@ -33,6 +33,12 @@ export interface SavedObjectsExportResultDetails { id: string; type: string; }>; + excludedObjectsCount: number; + excludedObjects: Array<{ + id: string; + type: string; + reason?: string; + }>; } function isExportDetails(object: any): object is SavedObjectsExportResultDetails { diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.tsx index 364b3ab0d9eb65..9b8474fc08bbd7 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.tsx @@ -258,7 +258,7 @@ describe('SavedObjectsTable', () => { }); }); - it('should display a warning is export contains missing references', async () => { + it('should display a warning if the export contains missing references', async () => { const mockSelectedSavedObjects = [ { id: '1', type: 'index-pattern' }, { id: '3', type: 'dashboard' }, @@ -280,6 +280,8 @@ describe('SavedObjectsTable', () => { exportedCount: 2, missingRefCount: 1, missingReferences: [{ id: '7', type: 'visualisation' }], + excludedObjectsCount: 0, + excludedObjects: [], })); const component = shallowRender({ savedObjectsClient: mockSavedObjectsClient }); @@ -303,6 +305,53 @@ describe('SavedObjectsTable', () => { }); }); + it('should display a specific message if the export contains excluded objects', async () => { + const mockSelectedSavedObjects = [ + { id: '1', type: 'index-pattern' }, + { id: '3', type: 'dashboard' }, + ] as SavedObjectWithMetadata[]; + + const mockSavedObjects = mockSelectedSavedObjects.map((obj) => ({ + _id: obj.id, + _source: {}, + })); + + const mockSavedObjectsClient = { + ...defaultProps.savedObjectsClient, + bulkGet: jest.fn().mockImplementation(() => ({ + savedObjects: mockSavedObjects, + })), + }; + + extractExportDetailsMock.mockImplementation(() => ({ + exportedCount: 2, + missingRefCount: 0, + missingReferences: [], + excludedObjectsCount: 1, + excludedObjects: [{ id: '7', type: 'visualisation' }], + })); + + const component = shallowRender({ savedObjectsClient: mockSavedObjectsClient }); + + // Ensure all promises resolve + await new Promise((resolve) => process.nextTick(resolve)); + // Ensure the state changes are reflected + component.update(); + + // Set some as selected + component.instance().onSelectionChanged(mockSelectedSavedObjects); + + await component.instance().onExport(true); + + expect(fetchExportObjectsMock).toHaveBeenCalledWith(http, mockSelectedSavedObjects, true); + expect(notifications.toasts.addSuccess).toHaveBeenCalledWith({ + title: + 'Your file is downloading in the background. ' + + 'Some objects were excluded from the export. ' + + 'Please see the last line in the exported file for a list of excluded objects.', + }); + }); + it('should allow the user to choose when exporting all', async () => { const component = shallowRender(); diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx index e23c74bc1bc195..42c1220ef55407 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx @@ -358,7 +358,7 @@ export class SavedObjectsTable extends Component { @@ -395,31 +395,45 @@ export class SavedObjectsTable extends Component { + showExportCompleteMessage = (exportDetails: SavedObjectsExportResultDetails | undefined) => { const { notifications } = this.props; - if (exportDetails && exportDetails.missingReferences.length > 0) { - notifications.toasts.addWarning({ - title: i18n.translate( - 'savedObjectsManagement.objectsTable.export.successWithMissingRefsNotification', - { - defaultMessage: - 'Your file is downloading in the background. ' + - 'Some related objects could not be found. ' + - 'Please see the last line in the exported file for a list of missing objects.', - } - ), - }); - } else { - notifications.toasts.addSuccess({ - title: i18n.translate('savedObjectsManagement.objectsTable.export.successNotification', { - defaultMessage: 'Your file is downloading in the background', - }), - }); + if (exportDetails) { + if (exportDetails.missingReferences.length > 0) { + return notifications.toasts.addWarning({ + title: i18n.translate( + 'savedObjectsManagement.objectsTable.export.successWithMissingRefsNotification', + { + defaultMessage: + 'Your file is downloading in the background. ' + + 'Some related objects could not be found. ' + + 'Please see the last line in the exported file for a list of missing objects.', + } + ), + }); + } + if (exportDetails.excludedObjects.length > 0) { + return notifications.toasts.addSuccess({ + title: i18n.translate( + 'savedObjectsManagement.objectsTable.export.successWithExcludedObjectsNotification', + { + defaultMessage: + 'Your file is downloading in the background. ' + + 'Some objects were excluded from the export. ' + + 'Please see the last line in the exported file for a list of excluded objects.', + } + ), + }); + } } + return notifications.toasts.addSuccess({ + title: i18n.translate('savedObjectsManagement.objectsTable.export.successNotification', { + defaultMessage: 'Your file is downloading in the background', + }), + }); }; finishImport = () => { diff --git a/src/plugins/vis_type_timeseries/public/application/components/markdown_editor.js b/src/plugins/vis_type_timeseries/public/application/components/markdown_editor.js index 684225786e1cca..b9aa70f5207af2 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/markdown_editor.js +++ b/src/plugins/vis_type_timeseries/public/application/components/markdown_editor.js @@ -15,10 +15,9 @@ import React, { Component } from 'react'; import { createTickFormatter } from './lib/tick_formatter'; import { convertSeriesToVars } from './lib/convert_series_to_vars'; import _ from 'lodash'; -import 'brace/mode/markdown'; -import 'brace/theme/github'; +import { CodeEditor, MarkdownLang } from '../../../../kibana_react/public'; -import { EuiText, EuiCodeBlock, EuiSpacer, EuiTitle, EuiCodeEditor } from '@elastic/eui'; +import { EuiText, EuiCodeBlock, EuiSpacer, EuiTitle } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; @@ -101,14 +100,13 @@ export class MarkdownEditor extends Component { return (
- diff --git a/src/plugins/vis_type_timeseries/public/application/components/panel_config/markdown.tsx b/src/plugins/vis_type_timeseries/public/application/components/panel_config/markdown.tsx index c33b4df914a816..7f82f95d250ead 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/panel_config/markdown.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/panel_config/markdown.tsx @@ -20,7 +20,6 @@ import { EuiSpacer, EuiTitle, EuiHorizontalRule, - EuiCodeEditor, } from '@elastic/eui'; // @ts-expect-error import less from 'less/lib/less-browser'; @@ -43,6 +42,7 @@ import { getDefaultQueryLanguage } from '../lib/get_default_query_language'; import { VisDataContext } from '../../contexts/vis_data_context'; import { PanelConfigProps, PANEL_CONFIG_TABS } from './types'; import { TimeseriesVisParams } from '../../../types'; +import { CodeEditor, CssLang } from '../../../../../kibana_react/public'; const lessC = less(window, { env: 'production' }); @@ -281,12 +281,10 @@ export class MarkdownPanelConfig extends Component< - diff --git a/test/functional/fixtures/es_archiver/saved_objects_management/export_exclusion/data.json b/test/functional/fixtures/es_archiver/saved_objects_management/export_exclusion/data.json new file mode 100644 index 00000000000000..f7015ee20251d8 --- /dev/null +++ b/test/functional/fixtures/es_archiver/saved_objects_management/export_exclusion/data.json @@ -0,0 +1,135 @@ +{ + "type": "doc", + "value": { + "index": ".kibana", + "type": "doc", + "id": "test-is-exportable:1", + "source": { + "test-is-exportable": { + "title": "obj 1", + "enabled": true + }, + "type": "test-is-exportable", + "migrationVersion": {}, + "updated_at": "2018-12-21T00:43:07.096Z", + "references": [ + { + "type": "test-is-exportable", + "id": "2", + "name": "ref-1" + }, + { + "type": "test-is-exportable", + "id": "3", + "name": "ref-2" + } + ] + } + } +} + +{ + "type": "doc", + "value": { + "index": ".kibana", + "type": "doc", + "id": "test-is-exportable:2", + "source": { + "test-is-exportable": { + "title": "obj 2", + "enabled": false + }, + "type": "test-is-exportable", + "migrationVersion": {}, + "updated_at": "2018-12-21T00:43:07.096Z", + "references": [] + } + } +} + +{ + "type": "doc", + "value": { + "index": ".kibana", + "type": "doc", + "id": "test-is-exportable:3", + "source": { + "test-is-exportable": { + "title": "obj 3", + "enabled": true + }, + "type": "test-is-exportable", + "migrationVersion": {}, + "updated_at": "2018-12-21T00:43:07.096Z", + "references": [ + { + "type": "test-is-exportable", + "id": "4", + "name": "ref-1" + }, + { + "type": "test-is-exportable", + "id": "5", + "name": "ref-2" + } + ] + } + } +} + +{ + "type": "doc", + "value": { + "index": ".kibana", + "type": "doc", + "id": "test-is-exportable:4", + "source": { + "test-is-exportable": { + "title": "obj 4", + "enabled": false + }, + "type": "test-is-exportable", + "migrationVersion": {}, + "updated_at": "2018-12-21T00:43:07.096Z", + "references": [] + } + } +} + +{ + "type": "doc", + "value": { + "index": ".kibana", + "type": "doc", + "id": "test-is-exportable:5", + "source": { + "test-is-exportable": { + "title": "obj 5", + "enabled": true + }, + "type": "test-is-exportable", + "migrationVersion": {}, + "updated_at": "2018-12-21T00:43:07.096Z", + "references": [] + } + } +} + +{ + "type": "doc", + "value": { + "index": ".kibana", + "type": "doc", + "id": "test-is-exportable:error", + "source": { + "test-is-exportable": { + "title": "obj error", + "enabled": true + }, + "type": "test-is-exportable", + "migrationVersion": {}, + "updated_at": "2018-12-21T00:43:07.096Z", + "references": [] + } + } +} diff --git a/test/functional/fixtures/es_archiver/saved_objects_management/export_exclusion/mappings.json b/test/functional/fixtures/es_archiver/saved_objects_management/export_exclusion/mappings.json new file mode 100644 index 00000000000000..abec2eeb77492b --- /dev/null +++ b/test/functional/fixtures/es_archiver/saved_objects_management/export_exclusion/mappings.json @@ -0,0 +1,505 @@ +{ + "type": "index", + "value": { + "index": ".kibana", + "settings": { + "index": { + "number_of_shards": "1", + "auto_expand_replicas": "0-1", + "number_of_replicas": "0" + } + }, + "mappings": { + "dynamic": "strict", + "properties": { + "test-export-transform": { + "properties": { + "title": { "type": "text" }, + "enabled": { "type": "boolean" } + } + }, + "test-is-exportable": { + "properties": { + "title": { "type": "text" }, + "enabled": { "type": "boolean" } + } + }, + "test-export-add": { + "properties": { + "title": { "type": "text" } + } + }, + "test-export-add-dep": { + "properties": { + "title": { "type": "text" } + } + }, + "test-export-transform-error": { + "properties": { + "title": { "type": "text" } + } + }, + "test-export-invalid-transform": { + "properties": { + "title": { "type": "text" } + } + }, + "apm-telemetry": { + "properties": { + "has_any_services": { + "type": "boolean" + }, + "services_per_agent": { + "properties": { + "go": { + "type": "long", + "null_value": 0 + }, + "java": { + "type": "long", + "null_value": 0 + }, + "js-base": { + "type": "long", + "null_value": 0 + }, + "nodejs": { + "type": "long", + "null_value": 0 + }, + "python": { + "type": "long", + "null_value": 0 + }, + "ruby": { + "type": "long", + "null_value": 0 + } + } + } + } + }, + "canvas-workpad": { + "dynamic": "false", + "properties": { + "@created": { + "type": "date" + }, + "@timestamp": { + "type": "date" + }, + "id": { + "type": "text", + "index": false + }, + "name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword" + } + } + } + } + }, + "config": { + "dynamic": "true", + "properties": { + "accessibility:disableAnimations": { + "type": "boolean" + }, + "buildNum": { + "type": "keyword" + }, + "dateFormat:tz": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "defaultIndex": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "telemetry:optIn": { + "type": "boolean" + } + } + }, + "dashboard": { + "properties": { + "description": { + "type": "text" + }, + "hits": { + "type": "integer" + }, + "kibanaSavedObjectMeta": { + "properties": { + "searchSourceJSON": { + "type": "text" + } + } + }, + "optionsJSON": { + "type": "text" + }, + "panelsJSON": { + "type": "text" + }, + "refreshInterval": { + "properties": { + "display": { + "type": "keyword" + }, + "pause": { + "type": "boolean" + }, + "section": { + "type": "integer" + }, + "value": { + "type": "integer" + } + } + }, + "timeFrom": { + "type": "keyword" + }, + "timeRestore": { + "type": "boolean" + }, + "timeTo": { + "type": "keyword" + }, + "title": { + "type": "text" + }, + "uiStateJSON": { + "type": "text" + }, + "version": { + "type": "integer" + } + } + }, + "map": { + "properties": { + "bounds": { + "dynamic": false, + "properties": {} + }, + "description": { + "type": "text" + }, + "layerListJSON": { + "type": "text" + }, + "mapStateJSON": { + "type": "text" + }, + "title": { + "type": "text" + }, + "uiStateJSON": { + "type": "text" + }, + "version": { + "type": "integer" + } + } + }, + "graph-workspace": { + "properties": { + "description": { + "type": "text" + }, + "kibanaSavedObjectMeta": { + "properties": { + "searchSourceJSON": { + "type": "text" + } + } + }, + "numLinks": { + "type": "integer" + }, + "numVertices": { + "type": "integer" + }, + "title": { + "type": "text" + }, + "version": { + "type": "integer" + }, + "wsState": { + "type": "text" + } + } + }, + "index-pattern": { + "properties": { + "fieldFormatMap": { + "type": "text" + }, + "fields": { + "type": "text" + }, + "intervalName": { + "type": "keyword" + }, + "notExpandable": { + "type": "boolean" + }, + "sourceFilters": { + "type": "text" + }, + "timeFieldName": { + "type": "keyword" + }, + "title": { + "type": "text" + }, + "type": { + "type": "keyword" + }, + "typeMeta": { + "type": "keyword" + } + } + }, + "kql-telemetry": { + "properties": { + "optInCount": { + "type": "long" + }, + "optOutCount": { + "type": "long" + } + } + }, + "migrationVersion": { + "dynamic": "true", + "properties": { + "index-pattern": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "space": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + }, + "namespace": { + "type": "keyword" + }, + "search": { + "properties": { + "columns": { + "type": "keyword" + }, + "description": { + "type": "text" + }, + "hits": { + "type": "integer" + }, + "kibanaSavedObjectMeta": { + "properties": { + "searchSourceJSON": { + "type": "text" + } + } + }, + "sort": { + "type": "keyword" + }, + "title": { + "type": "text" + }, + "version": { + "type": "integer" + } + } + }, + "server": { + "properties": { + "uuid": { + "type": "keyword" + } + } + }, + "space": { + "properties": { + "_reserved": { + "type": "boolean" + }, + "color": { + "type": "keyword" + }, + "description": { + "type": "text" + }, + "disabledFeatures": { + "type": "keyword" + }, + "initials": { + "type": "keyword" + }, + "name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 2048 + } + } + } + } + }, + "spaceId": { + "type": "keyword" + }, + "telemetry": { + "properties": { + "enabled": { + "type": "boolean" + } + } + }, + "timelion-sheet": { + "properties": { + "description": { + "type": "text" + }, + "hits": { + "type": "integer" + }, + "kibanaSavedObjectMeta": { + "properties": { + "searchSourceJSON": { + "type": "text" + } + } + }, + "timelion_chart_height": { + "type": "integer" + }, + "timelion_columns": { + "type": "integer" + }, + "timelion_interval": { + "type": "keyword" + }, + "timelion_other_interval": { + "type": "keyword" + }, + "timelion_rows": { + "type": "integer" + }, + "timelion_sheet": { + "type": "text" + }, + "title": { + "type": "text" + }, + "version": { + "type": "integer" + } + } + }, + "type": { + "type": "keyword" + }, + "updated_at": { + "type": "date" + }, + "url": { + "properties": { + "accessCount": { + "type": "long" + }, + "accessDate": { + "type": "date" + }, + "createDate": { + "type": "date" + }, + "url": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 2048 + } + } + } + } + }, + "visualization": { + "properties": { + "description": { + "type": "text" + }, + "kibanaSavedObjectMeta": { + "properties": { + "searchSourceJSON": { + "type": "text" + } + } + }, + "savedSearchId": { + "type": "keyword" + }, + "title": { + "type": "text" + }, + "uiStateJSON": { + "type": "text" + }, + "version": { + "type": "integer" + }, + "visState": { + "type": "text" + } + } + }, + "references": { + "properties": { + "id": { + "type": "keyword" + }, + "name": { + "type": "keyword" + }, + "type": { + "type": "keyword" + } + }, + "type": "nested" + } + } + } + } +} diff --git a/test/functional/page_objects/visual_builder_page.ts b/test/functional/page_objects/visual_builder_page.ts index d796067372fa87..6e263dd1cdbbf5 100644 --- a/test/functional/page_objects/visual_builder_page.ts +++ b/test/functional/page_objects/visual_builder_page.ts @@ -132,19 +132,18 @@ export class VisualBuilderPageObject extends FtrService { } public async clearMarkdown() { - // Since we use ACE editor and that isn't really storing its value inside - // a textarea we must really select all text and remove it, and cannot use - // clearValue(). await this.retry.waitForWithTimeout('text area is cleared', 20000, async () => { - const editor = await this.testSubjects.find('codeEditorContainer'); - const $ = await editor.parseDomContent(); - const value = $('.ace_line').text(); - if (value.length > 0) { - this.log.debug('Clearing text area input'); - this.waitForMarkdownTextAreaCleaned(); - } - - return value.length === 0; + const input = await this.find.byCssSelector('.tvbMarkdownEditor__editor textarea'); + await input.clickMouseButton(); + await input.clearValueWithKeyboard(); + + const linesContainer = await this.find.byCssSelector( + '.tvbMarkdownEditor__editor .view-lines' + ); + // lines of code in monaco-editor + // text is not present in textarea + const lines = await linesContainer.findAllByClassName('mtk1'); + return lines.length === 0; }); } diff --git a/test/plugin_functional/plugins/saved_object_export_transforms/server/plugin.ts b/test/plugin_functional/plugins/saved_object_export_transforms/server/plugin.ts index 408ac03dd946bf..15afdb229b1fdf 100644 --- a/test/plugin_functional/plugins/saved_object_export_transforms/server/plugin.ts +++ b/test/plugin_functional/plugins/saved_object_export_transforms/server/plugin.ts @@ -152,6 +152,30 @@ export class SavedObjectExportTransformsPlugin implements Plugin { getTitle: (obj) => obj.attributes.title, }, }); + + // example of a SO type implementing the `isExportable` API + savedObjects.registerType<{ enabled: boolean; title: string }>({ + name: 'test-is-exportable', + hidden: false, + namespaceType: 'single', + mappings: { + properties: { + title: { type: 'text' }, + enabled: { type: 'boolean' }, + }, + }, + management: { + defaultSearchField: 'title', + importableAndExportable: true, + getTitle: (obj) => obj.attributes.title, + isExportable: (obj) => { + if (obj.id === 'error') { + throw new Error('something went wrong'); + } + return obj.attributes.enabled === true; + }, + }, + }); } public start() {} diff --git a/test/plugin_functional/test_suites/saved_objects_management/export_transform.ts b/test/plugin_functional/test_suites/saved_objects_management/export_transform.ts index 0351c5abdde461..8437e050091fbe 100644 --- a/test/plugin_functional/test_suites/saved_objects_management/export_transform.ts +++ b/test/plugin_functional/test_suites/saved_objects_management/export_transform.ts @@ -8,6 +8,7 @@ import expect from '@kbn/expect'; import type { SavedObject } from '../../../../src/core/types'; +import type { SavedObjectsExportResultDetails } from '../../../../src/core/server'; import { PluginFunctionalProviderContext } from '../../services'; function parseNdJson(input: string): Array> { @@ -139,7 +140,7 @@ export default function ({ getService }: PluginFunctionalProviderContext) { }); }); - describe('FOO nested export transforms', () => { + describe('nested export transforms', () => { before(async () => { await esArchiver.load( 'test/functional/fixtures/es_archiver/saved_objects_management/nested_export_transform' @@ -183,5 +184,121 @@ export default function ({ getService }: PluginFunctionalProviderContext) { }); }); }); + + describe('isExportable API', () => { + before(async () => { + await esArchiver.load( + 'test/functional/fixtures/es_archiver/saved_objects_management/export_exclusion' + ); + }); + + after(async () => { + await esArchiver.unload( + 'test/functional/fixtures/es_archiver/saved_objects_management/export_exclusion' + ); + }); + + it('should only export objects returning `true` for `isExportable`', async () => { + await supertest + .post('/api/saved_objects/_export') + .set('kbn-xsrf', 'true') + .send({ + objects: [ + { + type: 'test-is-exportable', + id: '1', + }, + ], + includeReferencesDeep: true, + excludeExportDetails: true, + }) + .expect(200) + .then((resp) => { + const objects = parseNdJson(resp.text).sort((obj1, obj2) => + obj1.id.localeCompare(obj2.id) + ); + expect(objects.map((obj) => `${obj.type}:${obj.id}`)).to.eql([ + 'test-is-exportable:1', + 'test-is-exportable:3', + 'test-is-exportable:5', + ]); + }); + }); + + it('lists objects that got filtered', async () => { + await supertest + .post('/api/saved_objects/_export') + .set('kbn-xsrf', 'true') + .send({ + objects: [ + { + type: 'test-is-exportable', + id: '1', + }, + ], + includeReferencesDeep: true, + excludeExportDetails: false, + }) + .expect(200) + .then((resp) => { + const objects = parseNdJson(resp.text); + const exportDetails = (objects[ + objects.length - 1 + ] as unknown) as SavedObjectsExportResultDetails; + + expect(exportDetails.excludedObjectsCount).to.eql(2); + expect(exportDetails.excludedObjects).to.eql([ + { + type: 'test-is-exportable', + id: '2', + reason: 'excluded', + }, + { + type: 'test-is-exportable', + id: '4', + reason: 'excluded', + }, + ]); + }); + }); + + it('excludes objects if `isExportable` throws', async () => { + await supertest + .post('/api/saved_objects/_export') + .set('kbn-xsrf', 'true') + .send({ + objects: [ + { + type: 'test-is-exportable', + id: '5', + }, + { + type: 'test-is-exportable', + id: 'error', + }, + ], + includeReferencesDeep: true, + excludeExportDetails: false, + }) + .expect(200) + .then((resp) => { + const objects = parseNdJson(resp.text); + expect(objects.length).to.eql(2); + expect([objects[0]].map((obj) => `${obj.type}:${obj.id}`)).to.eql([ + 'test-is-exportable:5', + ]); + const exportDetails = (objects[ + objects.length - 1 + ] as unknown) as SavedObjectsExportResultDetails; + expect(exportDetails.excludedObjects).to.eql([ + { + type: 'test-is-exportable', + id: 'error', + reason: 'predicate_error', + }, + ]); + }); + }); + }); }); } diff --git a/typings/index.d.ts b/typings/index.d.ts index c7186a0e5795b0..2a5c5e3fa430f0 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -33,3 +33,7 @@ declare module 'axios/lib/adapters/xhr'; // See https://github.com/storybookjs/storybook/issues/11684 declare module 'react-syntax-highlighter/dist/cjs/create-element'; declare module 'react-syntax-highlighter/dist/cjs/prism-light'; + +// Monaco languages support +declare module 'monaco-editor/esm/vs/basic-languages/markdown/markdown'; +declare module 'monaco-editor/esm/vs/basic-languages/css/css'; diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/index.tsx b/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/index.tsx index e09cc2a81c927d..abcacbe89587b7 100644 --- a/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/index.tsx +++ b/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/index.tsx @@ -15,7 +15,7 @@ import { EuiFlexItem, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { ESFilter } from 'typings/elasticsearch'; +import { ESFilter } from 'src/core/types/elasticsearch'; import { useLocalUIFilters } from '../hooks/useLocalUIFilters'; import { uxFiltersByName, diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/queries.ts b/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/queries.ts index 5fe6bc725ef281..12f1fc0f0faea1 100644 --- a/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/queries.ts +++ b/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/queries.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ESFilter } from 'typings/elasticsearch'; +import { ESFilter } from 'src/core/types/elasticsearch'; import { SERVICE_ENVIRONMENT } from '../../../../../common/elasticsearch_fieldnames'; import { ENVIRONMENT_ALL, diff --git a/x-pack/plugins/apm/public/components/shared/KueryBar/get_bool_filter.ts b/x-pack/plugins/apm/public/components/shared/KueryBar/get_bool_filter.ts index c86cf769d75290..150a4d9efc2cb7 100644 --- a/x-pack/plugins/apm/public/components/shared/KueryBar/get_bool_filter.ts +++ b/x-pack/plugins/apm/public/components/shared/KueryBar/get_bool_filter.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ESFilter } from '../../../../../../../typings/elasticsearch'; +import { ESFilter } from '../../../../../../../src/core/types/elasticsearch'; import { ERROR_GROUP_ID, PROCESSOR_EVENT, diff --git a/x-pack/plugins/apm/public/utils/testHelpers.tsx b/x-pack/plugins/apm/public/utils/testHelpers.tsx index 877dec14ca1b0b..9a1d4da8ece7cc 100644 --- a/x-pack/plugins/apm/public/utils/testHelpers.tsx +++ b/x-pack/plugins/apm/public/utils/testHelpers.tsx @@ -19,7 +19,7 @@ import { EuiThemeProvider } from '../../../../../src/plugins/kibana_react/common import { ESSearchRequest, ESSearchResponse, -} from '../../../../../typings/elasticsearch'; +} from '../../../../../src/core/types/elasticsearch'; import { PromiseReturnType } from '../../../observability/typings/common'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { APMConfig } from '../../server'; diff --git a/x-pack/plugins/apm/scripts/shared/get_es_client.ts b/x-pack/plugins/apm/scripts/shared/get_es_client.ts index 7a8e09423ff15d..3accb832fb0edf 100644 --- a/x-pack/plugins/apm/scripts/shared/get_es_client.ts +++ b/x-pack/plugins/apm/scripts/shared/get_es_client.ts @@ -10,7 +10,7 @@ import { ApiKeyAuth, BasicAuth } from '@elastic/elasticsearch/lib/pool'; import { ESSearchResponse, ESSearchRequest, -} from '../../../../../typings/elasticsearch'; +} from '../../../../../src/core/types/elasticsearch'; export type ESClient = ReturnType; diff --git a/x-pack/plugins/apm/server/lib/alerts/alerting_es_client.ts b/x-pack/plugins/apm/server/lib/alerts/alerting_es_client.ts index 7d5b7d594bdf95..8b4d3e2186c84e 100644 --- a/x-pack/plugins/apm/server/lib/alerts/alerting_es_client.ts +++ b/x-pack/plugins/apm/server/lib/alerts/alerting_es_client.ts @@ -8,7 +8,7 @@ import { ESSearchRequest, ESSearchResponse, -} from '../../../../../../typings/elasticsearch'; +} from '../../../../../../src/core/types/elasticsearch'; import { AlertServices } from '../../../../alerting/server'; export async function alertingEsClient({ diff --git a/x-pack/plugins/apm/server/lib/alerts/register_transaction_duration_anomaly_alert_type.ts b/x-pack/plugins/apm/server/lib/alerts/register_transaction_duration_anomaly_alert_type.ts index 4ced6e6abb2511..f640925b0a0fa0 100644 --- a/x-pack/plugins/apm/server/lib/alerts/register_transaction_duration_anomaly_alert_type.ts +++ b/x-pack/plugins/apm/server/lib/alerts/register_transaction_duration_anomaly_alert_type.ts @@ -7,7 +7,7 @@ import { schema } from '@kbn/config-schema'; import { compact } from 'lodash'; -import { ESSearchResponse } from 'typings/elasticsearch'; +import { ESSearchResponse } from 'src/core/types/elasticsearch'; import { QueryDslQueryContainer } from '@elastic/elasticsearch/api/types'; import { ALERT_EVALUATION_THRESHOLD, diff --git a/x-pack/plugins/apm/server/lib/apm_telemetry/collect_data_telemetry/index.ts b/x-pack/plugins/apm/server/lib/apm_telemetry/collect_data_telemetry/index.ts index 87686d2c30cae4..22a2090dbb6cdb 100644 --- a/x-pack/plugins/apm/server/lib/apm_telemetry/collect_data_telemetry/index.ts +++ b/x-pack/plugins/apm/server/lib/apm_telemetry/collect_data_telemetry/index.ts @@ -11,7 +11,7 @@ import { IndicesStats } from '@elastic/elasticsearch/api/requestParams'; import { ESSearchRequest, ESSearchResponse, -} from '../../../../../../../typings/elasticsearch'; +} from '../../../../../../../src/core/types/elasticsearch'; import { ApmIndicesConfig } from '../../settings/apm_indices/get_apm_indices'; import { tasks } from './tasks'; import { APMDataTelemetry } from '../types'; diff --git a/x-pack/plugins/apm/server/lib/correlations/errors/get_correlations_for_failed_transactions.ts b/x-pack/plugins/apm/server/lib/correlations/errors/get_correlations_for_failed_transactions.ts index 11e9f99ddb356b..081c66dc2c4712 100644 --- a/x-pack/plugins/apm/server/lib/correlations/errors/get_correlations_for_failed_transactions.ts +++ b/x-pack/plugins/apm/server/lib/correlations/errors/get_correlations_for_failed_transactions.ts @@ -11,8 +11,8 @@ import { processSignificantTermAggs, TopSigTerm, } from '../process_significant_term_aggs'; -import { AggregationOptionsByType } from '../../../../../../../typings/elasticsearch'; -import { ESFilter } from '../../../../../../../typings/elasticsearch'; +import { AggregationOptionsByType } from '../../../../../../../src/core/types/elasticsearch'; +import { ESFilter } from '../../../../../../../src/core/types/elasticsearch'; import { EVENT_OUTCOME } from '../../../../common/elasticsearch_fieldnames'; import { ProcessorEvent } from '../../../../common/processor_event'; import { Setup, SetupTimeRange } from '../../helpers/setup_request'; diff --git a/x-pack/plugins/apm/server/lib/correlations/get_filters.ts b/x-pack/plugins/apm/server/lib/correlations/get_filters.ts index 92fc9c5d9622b2..61fec492ad38ec 100644 --- a/x-pack/plugins/apm/server/lib/correlations/get_filters.ts +++ b/x-pack/plugins/apm/server/lib/correlations/get_filters.ts @@ -6,7 +6,7 @@ */ import { Setup, SetupTimeRange } from '../helpers/setup_request'; -import { ESFilter } from '../../../../../../typings/elasticsearch'; +import { ESFilter } from '../../../../../../src/core/types/elasticsearch'; import { environmentQuery, rangeQuery, kqlQuery } from '../../utils/queries'; import { SERVICE_NAME, diff --git a/x-pack/plugins/apm/server/lib/correlations/latency/get_correlations_for_slow_transactions.ts b/x-pack/plugins/apm/server/lib/correlations/latency/get_correlations_for_slow_transactions.ts index c37b3e3ab82426..868a36958395bc 100644 --- a/x-pack/plugins/apm/server/lib/correlations/latency/get_correlations_for_slow_transactions.ts +++ b/x-pack/plugins/apm/server/lib/correlations/latency/get_correlations_for_slow_transactions.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { AggregationOptionsByType } from '../../../../../../../typings/elasticsearch'; +import { AggregationOptionsByType } from '../../../../../../../src/core/types/elasticsearch'; import { TRANSACTION_DURATION } from '../../../../common/elasticsearch_fieldnames'; import { ProcessorEvent } from '../../../../common/processor_event'; import { getDurationForPercentile } from './get_duration_for_percentile'; diff --git a/x-pack/plugins/apm/server/lib/correlations/latency/get_duration_for_percentile.ts b/x-pack/plugins/apm/server/lib/correlations/latency/get_duration_for_percentile.ts index a686980700d83a..902bdb8c7b511d 100644 --- a/x-pack/plugins/apm/server/lib/correlations/latency/get_duration_for_percentile.ts +++ b/x-pack/plugins/apm/server/lib/correlations/latency/get_duration_for_percentile.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ESFilter } from '../../../../../../../typings/elasticsearch'; +import { ESFilter } from '../../../../../../../src/core/types/elasticsearch'; import { TRANSACTION_DURATION } from '../../../../common/elasticsearch_fieldnames'; import { ProcessorEvent } from '../../../../common/processor_event'; import { Setup, SetupTimeRange } from '../../helpers/setup_request'; diff --git a/x-pack/plugins/apm/server/lib/correlations/latency/get_latency_distribution.ts b/x-pack/plugins/apm/server/lib/correlations/latency/get_latency_distribution.ts index be1bb631378cff..ad11d21a710d0d 100644 --- a/x-pack/plugins/apm/server/lib/correlations/latency/get_latency_distribution.ts +++ b/x-pack/plugins/apm/server/lib/correlations/latency/get_latency_distribution.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { AggregationOptionsByType } from '../../../../../../../typings/elasticsearch'; -import { ESFilter } from '../../../../../../../typings/elasticsearch'; +import { AggregationOptionsByType } from '../../../../../../../src/core/types/elasticsearch'; +import { ESFilter } from '../../../../../../../src/core/types/elasticsearch'; import { ProcessorEvent } from '../../../../common/processor_event'; import { Setup, SetupTimeRange } from '../../helpers/setup_request'; import { TopSigTerm } from '../process_significant_term_aggs'; diff --git a/x-pack/plugins/apm/server/lib/correlations/latency/get_max_latency.ts b/x-pack/plugins/apm/server/lib/correlations/latency/get_max_latency.ts index f2762086614b49..8b9a6c064b4a06 100644 --- a/x-pack/plugins/apm/server/lib/correlations/latency/get_max_latency.ts +++ b/x-pack/plugins/apm/server/lib/correlations/latency/get_max_latency.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ESFilter } from '../../../../../../../typings/elasticsearch'; +import { ESFilter } from '../../../../../../../src/core/types/elasticsearch'; import { TRANSACTION_DURATION } from '../../../../common/elasticsearch_fieldnames'; import { ProcessorEvent } from '../../../../common/processor_event'; import { Setup, SetupTimeRange } from '../../helpers/setup_request'; diff --git a/x-pack/plugins/apm/server/lib/correlations/process_significant_term_aggs.ts b/x-pack/plugins/apm/server/lib/correlations/process_significant_term_aggs.ts index cc1e32e47973d8..ecb751cad5a3f5 100644 --- a/x-pack/plugins/apm/server/lib/correlations/process_significant_term_aggs.ts +++ b/x-pack/plugins/apm/server/lib/correlations/process_significant_term_aggs.ts @@ -9,7 +9,7 @@ import { orderBy } from 'lodash'; import { AggregationOptionsByType, AggregationResultOf, -} from '../../../../../../typings/elasticsearch'; +} from '../../../../../../src/core/types/elasticsearch'; export interface TopSigTerm { fieldName: string; diff --git a/x-pack/plugins/apm/server/lib/errors/distribution/get_buckets.ts b/x-pack/plugins/apm/server/lib/errors/distribution/get_buckets.ts index a51464764f2b44..fa73ce8f2bc858 100644 --- a/x-pack/plugins/apm/server/lib/errors/distribution/get_buckets.ts +++ b/x-pack/plugins/apm/server/lib/errors/distribution/get_buckets.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ESFilter } from '../../../../../../../typings/elasticsearch'; +import { ESFilter } from '../../../../../../../src/core/types/elasticsearch'; import { ERROR_GROUP_ID, SERVICE_NAME, diff --git a/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/add_filter_to_exclude_legacy_data.ts b/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/add_filter_to_exclude_legacy_data.ts index 96bc8897e62fd0..60984d65f4499a 100644 --- a/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/add_filter_to_exclude_legacy_data.ts +++ b/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/add_filter_to_exclude_legacy_data.ts @@ -10,7 +10,7 @@ import { OBSERVER_VERSION_MAJOR } from '../../../../../common/elasticsearch_fiel import { ESSearchRequest, ESFilter, -} from '../../../../../../../../typings/elasticsearch'; +} from '../../../../../../../../src/core/types/elasticsearch'; /* Adds a range query to the ES request to exclude legacy data diff --git a/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.ts b/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.ts index 916a6981f286a9..0a464982b6e813 100644 --- a/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.ts +++ b/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.ts @@ -15,7 +15,7 @@ import { import { ESSearchRequest, InferSearchResponseOf, -} from '../../../../../../../../typings/elasticsearch'; +} from '../../../../../../../../src/core/types/elasticsearch'; import { unwrapEsResponse } from '../../../../../../observability/server'; import { ProcessorEvent } from '../../../../../common/processor_event'; import { APMError } from '../../../../../typings/es_schemas/ui/apm_error'; diff --git a/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/unpack_processor_events.ts b/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/unpack_processor_events.ts index 76e615f42bb645..8732ba81f9ae64 100644 --- a/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/unpack_processor_events.ts +++ b/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/unpack_processor_events.ts @@ -11,7 +11,7 @@ import { ProcessorEvent } from '../../../../../common/processor_event'; import { ESSearchRequest, ESFilter, -} from '../../../../../../../../typings/elasticsearch'; +} from '../../../../../../../../src/core/types/elasticsearch'; import { APMEventESSearchRequest } from '.'; import { ApmIndicesConfig, diff --git a/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_internal_es_client/index.ts b/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_internal_es_client/index.ts index e6b61a709ae353..eb3deb28893607 100644 --- a/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_internal_es_client/index.ts +++ b/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_internal_es_client/index.ts @@ -12,7 +12,7 @@ import { APMRouteHandlerResources } from '../../../../routes/typings'; import { ESSearchResponse, ESSearchRequest, -} from '../../../../../../../../typings/elasticsearch'; +} from '../../../../../../../../src/core/types/elasticsearch'; import { callAsyncWithDebug, getDebugBody, diff --git a/x-pack/plugins/apm/server/lib/helpers/transaction_error_rate.ts b/x-pack/plugins/apm/server/lib/helpers/transaction_error_rate.ts index b60a2a071e6dcb..41d9c373710c1e 100644 --- a/x-pack/plugins/apm/server/lib/helpers/transaction_error_rate.ts +++ b/x-pack/plugins/apm/server/lib/helpers/transaction_error_rate.ts @@ -10,7 +10,7 @@ import { EventOutcome } from '../../../common/event_outcome'; import { AggregationOptionsByType, AggregationResultOf, -} from '../../../../../../typings/elasticsearch'; +} from '../../../../../../src/core/types/elasticsearch'; export const getOutcomeAggregation = () => ({ terms: { diff --git a/x-pack/plugins/apm/server/lib/metrics/fetch_and_transform_metrics.ts b/x-pack/plugins/apm/server/lib/metrics/fetch_and_transform_metrics.ts index a91571bbc406d8..cd94eb85112823 100644 --- a/x-pack/plugins/apm/server/lib/metrics/fetch_and_transform_metrics.ts +++ b/x-pack/plugins/apm/server/lib/metrics/fetch_and_transform_metrics.ts @@ -6,7 +6,7 @@ */ import { Overwrite, Unionize } from 'utility-types'; -import { AggregationOptionsByType } from '../../../../../../typings/elasticsearch'; +import { AggregationOptionsByType } from '../../../../../../src/core/types/elasticsearch'; import { getMetricsProjection } from '../../projections/metrics'; import { mergeProjection } from '../../projections/util/merge_projection'; import { APMEventESSearchRequest } from '../helpers/create_es_client/create_apm_event_client'; diff --git a/x-pack/plugins/apm/server/lib/metrics/transform_metrics_chart.ts b/x-pack/plugins/apm/server/lib/metrics/transform_metrics_chart.ts index 17759f9094a871..999830dabefc47 100644 --- a/x-pack/plugins/apm/server/lib/metrics/transform_metrics_chart.ts +++ b/x-pack/plugins/apm/server/lib/metrics/transform_metrics_chart.ts @@ -6,7 +6,7 @@ */ import theme from '@elastic/eui/dist/eui_theme_light.json'; -import { ESSearchResponse } from '../../../../../../typings/elasticsearch'; +import { ESSearchResponse } from '../../../../../../src/core/types/elasticsearch'; import { getVizColorForIndex } from '../../../common/viz_colors'; import { GenericMetricsRequest } from './fetch_and_transform_metrics'; import { ChartBase } from './types'; diff --git a/x-pack/plugins/apm/server/lib/rum_client/ui_filters/get_es_filter.ts b/x-pack/plugins/apm/server/lib/rum_client/ui_filters/get_es_filter.ts index ce6de1e0076252..48beb9bca52413 100644 --- a/x-pack/plugins/apm/server/lib/rum_client/ui_filters/get_es_filter.ts +++ b/x-pack/plugins/apm/server/lib/rum_client/ui_filters/get_es_filter.ts @@ -9,7 +9,7 @@ import { uxLocalUIFilterNames, uxLocalUIFilters, } from '../../../../common/ux_ui_filter'; -import { ESFilter } from '../../../../../../../typings/elasticsearch'; +import { ESFilter } from '../../../../../../../src/core/types/elasticsearch'; import { UxUIFilters } from '../../../../typings/ui_filters'; import { environmentQuery } from '../../../utils/queries'; diff --git a/x-pack/plugins/apm/server/lib/service_map/get_service_anomalies.ts b/x-pack/plugins/apm/server/lib/service_map/get_service_anomalies.ts index 129a0ee73b8cb3..7ac56bcd9192d3 100644 --- a/x-pack/plugins/apm/server/lib/service_map/get_service_anomalies.ts +++ b/x-pack/plugins/apm/server/lib/service_map/get_service_anomalies.ts @@ -8,7 +8,7 @@ import Boom from '@hapi/boom'; import { sortBy, uniqBy } from 'lodash'; import { estypes } from '@elastic/elasticsearch'; -import { ESSearchResponse } from '../../../../../../typings/elasticsearch'; +import { ESSearchResponse } from '../../../../../../src/core/types/elasticsearch'; import { MlPluginSetup } from '../../../../ml/server'; import { PromiseReturnType } from '../../../../observability/typings/common'; import { getSeverity, ML_ERRORS } from '../../../common/anomaly_detection'; diff --git a/x-pack/plugins/apm/server/lib/service_map/get_service_map_service_node_info.ts b/x-pack/plugins/apm/server/lib/service_map/get_service_map_service_node_info.ts index 2709fb640d8ce3..2e0ac303e5157d 100644 --- a/x-pack/plugins/apm/server/lib/service_map/get_service_map_service_node_info.ts +++ b/x-pack/plugins/apm/server/lib/service_map/get_service_map_service_node_info.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ESFilter } from '../../../../../../typings/elasticsearch'; +import { ESFilter } from '../../../../../../src/core/types/elasticsearch'; import { METRIC_CGROUP_MEMORY_USAGE_BYTES, METRIC_SYSTEM_CPU_PERCENT, diff --git a/x-pack/plugins/apm/server/lib/service_map/get_trace_sample_ids.ts b/x-pack/plugins/apm/server/lib/service_map/get_trace_sample_ids.ts index 7894a95cf4d7e4..26d7d2d1ee316f 100644 --- a/x-pack/plugins/apm/server/lib/service_map/get_trace_sample_ids.ts +++ b/x-pack/plugins/apm/server/lib/service_map/get_trace_sample_ids.ts @@ -8,7 +8,7 @@ import Boom from '@hapi/boom'; import { sortBy, take, uniq } from 'lodash'; import { asMutableArray } from '../../../common/utils/as_mutable_array'; -import { ESFilter } from '../../../../../../typings/elasticsearch'; +import { ESFilter } from '../../../../../../src/core/types/elasticsearch'; import { SERVICE_ENVIRONMENT, SERVICE_NAME, diff --git a/x-pack/plugins/apm/server/lib/services/annotations/get_derived_service_annotations.ts b/x-pack/plugins/apm/server/lib/services/annotations/get_derived_service_annotations.ts index 202b5075d2ea74..08587217980fb7 100644 --- a/x-pack/plugins/apm/server/lib/services/annotations/get_derived_service_annotations.ts +++ b/x-pack/plugins/apm/server/lib/services/annotations/get_derived_service_annotations.ts @@ -6,7 +6,7 @@ */ import { isFiniteNumber } from '../../../../common/utils/is_finite_number'; -import { ESFilter } from '../../../../../../../typings/elasticsearch'; +import { ESFilter } from '../../../../../../../src/core/types/elasticsearch'; import { Annotation, AnnotationType } from '../../../../common/annotations'; import { SERVICE_NAME, diff --git a/x-pack/plugins/apm/server/lib/services/annotations/get_stored_annotations.ts b/x-pack/plugins/apm/server/lib/services/annotations/get_stored_annotations.ts index 3e1a8f26de6b42..56b7aa1f465b0e 100644 --- a/x-pack/plugins/apm/server/lib/services/annotations/get_stored_annotations.ts +++ b/x-pack/plugins/apm/server/lib/services/annotations/get_stored_annotations.ts @@ -12,7 +12,7 @@ import { unwrapEsResponse, WrappedElasticsearchClientError, } from '../../../../../observability/server'; -import { ESSearchResponse } from '../../../../../../../typings/elasticsearch'; +import { ESSearchResponse } from '../../../../../../../src/core/types/elasticsearch'; import { Annotation as ESAnnotation } from '../../../../../observability/common/annotations'; import { ScopedAnnotationsClient } from '../../../../../observability/server'; import { Annotation, AnnotationType } from '../../../../common/annotations'; diff --git a/x-pack/plugins/apm/server/lib/services/annotations/index.test.ts b/x-pack/plugins/apm/server/lib/services/annotations/index.test.ts index e2597a4a79cba4..6d65c971baa33a 100644 --- a/x-pack/plugins/apm/server/lib/services/annotations/index.test.ts +++ b/x-pack/plugins/apm/server/lib/services/annotations/index.test.ts @@ -8,7 +8,7 @@ import { ESSearchRequest, ESSearchResponse, -} from '../../../../../../../typings/elasticsearch'; +} from '../../../../../../../src/core/types/elasticsearch'; import { inspectSearchParams, SearchParamsMock, diff --git a/x-pack/plugins/apm/server/lib/services/get_service_instances/get_service_instances_system_metric_statistics.ts b/x-pack/plugins/apm/server/lib/services/get_service_instances/get_service_instances_system_metric_statistics.ts index 526ae19143f130..b817d4fb654ce7 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service_instances/get_service_instances_system_metric_statistics.ts +++ b/x-pack/plugins/apm/server/lib/services/get_service_instances/get_service_instances_system_metric_statistics.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { AggregationOptionsByType } from 'typings/elasticsearch'; +import { AggregationOptionsByType } from 'src/core/types/elasticsearch'; import { METRIC_CGROUP_MEMORY_USAGE_BYTES, METRIC_PROCESS_CPU_PERCENT, diff --git a/x-pack/plugins/apm/server/lib/services/get_throughput.ts b/x-pack/plugins/apm/server/lib/services/get_throughput.ts index b0cb917d302fc5..0490c31e7c63d3 100644 --- a/x-pack/plugins/apm/server/lib/services/get_throughput.ts +++ b/x-pack/plugins/apm/server/lib/services/get_throughput.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ESFilter } from '../../../../../../typings/elasticsearch'; +import { ESFilter } from '../../../../../../src/core/types/elasticsearch'; import { SERVICE_NAME, TRANSACTION_TYPE, diff --git a/x-pack/plugins/apm/server/lib/services/profiling/get_service_profiling_statistics.ts b/x-pack/plugins/apm/server/lib/services/profiling/get_service_profiling_statistics.ts index bb98abf724db4c..4e88c752aa50bc 100644 --- a/x-pack/plugins/apm/server/lib/services/profiling/get_service_profiling_statistics.ts +++ b/x-pack/plugins/apm/server/lib/services/profiling/get_service_profiling_statistics.ts @@ -15,7 +15,7 @@ import { getValueTypeConfig, } from '../../../../common/profiling'; import { ProcessorEvent } from '../../../../common/processor_event'; -import { ESFilter } from '../../../../../../../typings/elasticsearch'; +import { ESFilter } from '../../../../../../../src/core/types/elasticsearch'; import { PROFILE_STACK, PROFILE_TOP_ID, diff --git a/x-pack/plugins/apm/server/lib/settings/agent_configuration/convert_settings_to_string.ts b/x-pack/plugins/apm/server/lib/settings/agent_configuration/convert_settings_to_string.ts index 0b826ea10b6c4f..3ec10f6bf0c63d 100644 --- a/x-pack/plugins/apm/server/lib/settings/agent_configuration/convert_settings_to_string.ts +++ b/x-pack/plugins/apm/server/lib/settings/agent_configuration/convert_settings_to_string.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { SearchHit } from '../../../../../../../typings/elasticsearch'; +import { SearchHit } from '../../../../../../../src/core/types/elasticsearch'; import { AgentConfiguration } from '../../../../common/agent_configuration/configuration_types'; // needed for backwards compatability diff --git a/x-pack/plugins/apm/server/lib/settings/agent_configuration/find_exact_configuration.ts b/x-pack/plugins/apm/server/lib/settings/agent_configuration/find_exact_configuration.ts index 3543d38f7b5d1c..90f82442f9bfa1 100644 --- a/x-pack/plugins/apm/server/lib/settings/agent_configuration/find_exact_configuration.ts +++ b/x-pack/plugins/apm/server/lib/settings/agent_configuration/find_exact_configuration.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { SearchHit } from '../../../../../../../typings/elasticsearch'; +import { SearchHit } from '../../../../../../../src/core/types/elasticsearch'; import { AgentConfiguration } from '../../../../common/agent_configuration/configuration_types'; import { SERVICE_ENVIRONMENT, diff --git a/x-pack/plugins/apm/server/lib/settings/agent_configuration/search_configurations.ts b/x-pack/plugins/apm/server/lib/settings/agent_configuration/search_configurations.ts index 4e27953b3a315d..1e37ae91085738 100644 --- a/x-pack/plugins/apm/server/lib/settings/agent_configuration/search_configurations.ts +++ b/x-pack/plugins/apm/server/lib/settings/agent_configuration/search_configurations.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { SearchHit } from '../../../../../../../typings/elasticsearch'; +import { SearchHit } from '../../../../../../../src/core/types/elasticsearch'; import { SERVICE_NAME, SERVICE_ENVIRONMENT, diff --git a/x-pack/plugins/apm/server/lib/transaction_groups/fetcher.ts b/x-pack/plugins/apm/server/lib/transaction_groups/fetcher.ts index c1bf363b49d1c0..85f36b3999060b 100644 --- a/x-pack/plugins/apm/server/lib/transaction_groups/fetcher.ts +++ b/x-pack/plugins/apm/server/lib/transaction_groups/fetcher.ts @@ -9,7 +9,7 @@ import { sortBy, take } from 'lodash'; import moment from 'moment'; import { Unionize } from 'utility-types'; import { asMutableArray } from '../../../common/utils/as_mutable_array'; -import { AggregationOptionsByType } from '../../../../../../typings/elasticsearch'; +import { AggregationOptionsByType } from '../../../../../../src/core/types/elasticsearch'; import { PromiseReturnType } from '../../../../observability/typings/common'; import { SERVICE_NAME, diff --git a/x-pack/plugins/apm/server/lib/transactions/get_anomaly_data/fetcher.ts b/x-pack/plugins/apm/server/lib/transactions/get_anomaly_data/fetcher.ts index b105f3b5c0a307..558db179393544 100644 --- a/x-pack/plugins/apm/server/lib/transactions/get_anomaly_data/fetcher.ts +++ b/x-pack/plugins/apm/server/lib/transactions/get_anomaly_data/fetcher.ts @@ -6,7 +6,7 @@ */ import { QueryDslQueryContainer } from '@elastic/elasticsearch/api/types'; -import { ESSearchResponse } from '../../../../../../../typings/elasticsearch'; +import { ESSearchResponse } from '../../../../../../../src/core/types/elasticsearch'; import { PromiseReturnType } from '../../../../../observability/typings/common'; import { rangeQuery } from '../../../../server/utils/queries'; import { asMutableArray } from '../../../../common/utils/as_mutable_array'; diff --git a/x-pack/plugins/apm/server/lib/transactions/get_latency_charts/index.ts b/x-pack/plugins/apm/server/lib/transactions/get_latency_charts/index.ts index 2d350090fa28b7..1a183e15fee2b8 100644 --- a/x-pack/plugins/apm/server/lib/transactions/get_latency_charts/index.ts +++ b/x-pack/plugins/apm/server/lib/transactions/get_latency_charts/index.ts @@ -6,7 +6,7 @@ */ import { offsetPreviousPeriodCoordinates } from '../../../../common/utils/offset_previous_period_coordinate'; -import { ESFilter } from '../../../../../../../typings/elasticsearch'; +import { ESFilter } from '../../../../../../../src/core/types/elasticsearch'; import { PromiseReturnType } from '../../../../../observability/typings/common'; import { SERVICE_NAME, diff --git a/x-pack/plugins/apm/server/lib/transactions/get_throughput_charts/index.ts b/x-pack/plugins/apm/server/lib/transactions/get_throughput_charts/index.ts index f4d9236395252c..ed85e700c3473f 100644 --- a/x-pack/plugins/apm/server/lib/transactions/get_throughput_charts/index.ts +++ b/x-pack/plugins/apm/server/lib/transactions/get_throughput_charts/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ESFilter } from '../../../../../../../typings/elasticsearch'; +import { ESFilter } from '../../../../../../../src/core/types/elasticsearch'; import { PromiseReturnType } from '../../../../../observability/typings/common'; import { SERVICE_NAME, diff --git a/x-pack/plugins/apm/server/projections/typings.ts b/x-pack/plugins/apm/server/projections/typings.ts index 60a3317af1864d..0843fa4c9dd640 100644 --- a/x-pack/plugins/apm/server/projections/typings.ts +++ b/x-pack/plugins/apm/server/projections/typings.ts @@ -5,7 +5,7 @@ * 2.0. */ import { estypes } from '@elastic/elasticsearch'; -import { AggregationOptionsByType } from '../../../../../typings/elasticsearch'; +import { AggregationOptionsByType } from '../../../../../src/core/types/elasticsearch'; import { APMEventESSearchRequest } from '../lib/helpers/create_es_client/create_apm_event_client'; export type Projection = Omit & { diff --git a/x-pack/plugins/apm/server/utils/queries.ts b/x-pack/plugins/apm/server/utils/queries.ts index f21ef9de0283f4..a82b49a84dc6e3 100644 --- a/x-pack/plugins/apm/server/utils/queries.ts +++ b/x-pack/plugins/apm/server/utils/queries.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ESFilter } from '../../../../../typings/elasticsearch'; +import { ESFilter } from '../../../../../src/core/types/elasticsearch'; import { SERVICE_ENVIRONMENT } from '../../common/elasticsearch_fieldnames'; import { ENVIRONMENT_ALL, diff --git a/x-pack/plugins/apm/server/utils/test_helpers.tsx b/x-pack/plugins/apm/server/utils/test_helpers.tsx index 9f271c566e2fad..1d0a47ece9a60b 100644 --- a/x-pack/plugins/apm/server/utils/test_helpers.tsx +++ b/x-pack/plugins/apm/server/utils/test_helpers.tsx @@ -10,7 +10,7 @@ import { PromiseReturnType } from '../../../observability/typings/common'; import { ESSearchRequest, ESSearchResponse, -} from '../../../../../typings/elasticsearch'; +} from '../../../../../src/core/types/elasticsearch'; import { UxUIFilters } from '../../typings/ui_filters'; interface Options { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/connect_instance.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/connect_instance.tsx index fd45d779e6f2a6..e3b34050593fa8 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/connect_instance.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/connect_instance.tsx @@ -161,13 +161,13 @@ export const ConnectInstance: React.FC = ({ const permissionField = ( <> - +

{CONNECT_DOC_PERMISSIONS_TITLE}

- + {!needsPermissions && ( = ({ )} - {!indexPermissionsValue && ( <> - - +

{CONNECT_NOT_SYNCED_TEXT} {needsPermissions && whichDocsLink} diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/source_features.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/source_features.tsx index 7a66efe4ba5f46..0f170be8ba076f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/source_features.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/source_features.tsx @@ -63,20 +63,20 @@ export const SourceFeatures: React.FC = ({ features, objTy )} - + {title} - {children} + {children} ); }; const SyncFrequencyFeature = ( - +

= ({ features, objTy const SyncedItemsFeature = ( <> - +

{SOURCE_FEATURES_SEARCHABLE}

- +
    {objTypes!.map((objType, i) => (
  • {objType}
  • @@ -178,7 +178,7 @@ export const SourceFeatures: React.FC = ({ features, objTy return ( <> - +

    Included features

    diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_form.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_form.tsx index a44edb5ce9a422..25a09932428227 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_form.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_form.tsx @@ -29,6 +29,7 @@ import styled from 'styled-components'; import { dataTypes } from '../../../../../../common'; import type { NewAgentPolicy, AgentPolicy } from '../../../types'; import { isValidNamespace } from '../../../services'; +import { useStartServices } from '../../../hooks'; import { AgentPolicyDeleteProvider } from './agent_policy_delete_provider'; @@ -83,6 +84,7 @@ export const AgentPolicyForm: React.FunctionComponent = ({ isEditing = false, onDelete = () => {}, }) => { + const { docLinks } = useStartServices(); const [touchedFields, setTouchedFields] = useState<{ [key: string]: boolean }>({}); const fields: Array<{ name: 'name' | 'description' | 'namespace'; @@ -174,10 +176,7 @@ export const AgentPolicyForm: React.FunctionComponent = ({ defaultMessage="Namespaces are a user-configurable arbitrary grouping that makes it easier to search for data and manage user permissions. A policy namespace is used to name its integration's data streams. {fleetUserGuide}." values={{ fleetUserGuide: ( - + {i18n.translate( 'xpack.fleet.agentPolicyForm.nameSpaceFieldDescription.fleetUserGuideLabel', { defaultMessage: 'Learn more' } diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/step_define_package_policy.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/step_define_package_policy.tsx index 7444bed6ed3fdb..c276e67cabbffa 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/step_define_package_policy.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/step_define_package_policy.tsx @@ -29,6 +29,7 @@ import type { } from '../../../types'; import { packageToPackagePolicy, pkgKeyFromPackageInfo } from '../../../services'; import { Loading } from '../../../components'; +import { useStartServices } from '../../../hooks'; import { isAdvancedVar } from './services'; import type { PackagePolicyValidationResults } from './services'; @@ -52,6 +53,7 @@ export const StepDefinePackagePolicy: React.FunctionComponent<{ validationResults, submitAttempted, }) => { + const { docLinks } = useStartServices(); // Form show/hide states const [isShowingAdvanced, setIsShowingAdvanced] = useState(false); @@ -167,10 +169,7 @@ export const StepDefinePackagePolicy: React.FunctionComponent<{ defaultMessage="Change the default namespace inherited from the selected Agent policy. This setting changes the name of the integration's data stream. {learnMore}." values={{ learnMore: ( - + {i18n.translate( 'xpack.fleet.createPackagePolicy.stepConfigure.packagePolicyNamespaceHelpLearnMoreLabel', { defaultMessage: 'Learn more' } diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_requirements_page/es_requirements_page.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_requirements_page/es_requirements_page.tsx index 5335432a136137..b4e6f1007536f6 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_requirements_page/es_requirements_page.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_requirements_page/es_requirements_page.tsx @@ -24,6 +24,7 @@ import { import { WithoutHeaderLayout } from '../../../layouts'; import type { GetFleetStatusResponse } from '../../../types'; +import { useStartServices } from '../../../hooks'; export const RequirementItem: React.FunctionComponent<{ isMissing: boolean }> = ({ isMissing, @@ -50,6 +51,8 @@ export const RequirementItem: React.FunctionComponent<{ isMissing: boolean }> = export const MissingESRequirementsPage: React.FunctionComponent<{ missingRequirements: GetFleetStatusResponse['missing_requirements']; }> = ({ missingRequirements }) => { + const { docLinks } = useStartServices(); + return ( @@ -79,7 +82,7 @@ export const MissingESRequirementsPage: React.FunctionComponent<{ values={{ esSecurityLink: ( @@ -104,7 +107,7 @@ export const MissingESRequirementsPage: React.FunctionComponent<{ true: true, apiKeyLink: ( @@ -128,11 +131,7 @@ xpack.security.authc.api_key.enabled: true`} defaultMessage="For more information, read our {link} guide." values={{ link: ( - + void; }): EuiStepProps => { + const { docLinks } = useStartServices(); + return { title: i18n.translate('xpack.fleet.fleetServerSetup.stepInstallAgentTitle', { defaultMessage: 'Start Fleet Server', @@ -147,7 +149,11 @@ export const FleetServerCommandStep = ({ defaultMessage="From the agent directory, copy and run the appropriate quick start command to start an Elastic Agent as a Fleet Server using the generated token and a self-signed certificate. See the {userGuideLink} for instructions on using your own certificates for production deployment. All commands require administrator privileges." values={{ userGuideLink: ( - + + { platform, setPlatform, } = useFleetServerInstructions(); + const { docLinks } = useStartServices(); return ( @@ -304,7 +307,11 @@ const OnPremInstructions: React.FC = () => { defaultMessage="A Fleet Server is required before you can enroll agents with Fleet. See the {userGuideLink} for more information." values={{ userGuideLink: ( - + { }; const CloudInstructions: React.FC<{ deploymentUrl: string }> = ({ deploymentUrl }) => { + const { docLinks } = useStartServices(); + return ( = ({ deploymentUrl defaultMessage="A Fleet Server is required before you can enroll agents with Fleet. You can add one to your deployment by enabling APM & Fleet. For more information see the {link}" values={{ link: ( - + = ({ onClose }) => { const { getAssetsPath } = useLink(); - const { notifications, cloud } = useStartServices(); + const { notifications, cloud, docLinks } = useStartServices(); const isCloud = !!cloud?.cloudId; @@ -163,7 +163,11 @@ export const FleetServerUpgradeModal: React.FunctionComponent = ({ onClos ), link: ( - + { const { setModal } = useUrlModal(); + const { docLinks } = useStartServices(); + return ( { defaultMessage="A URL for your Fleet Server host is required to enroll agents with Fleet. You can add this information in Fleet Settings. For more information, see the {link}." values={{ link: ( - + void; } export const AlphaFlyout: React.FunctionComponent = ({ onClose }) => { + const { docLinks } = useStartServices(); + return ( @@ -49,11 +53,7 @@ export const AlphaFlyout: React.FunctionComponent = ({ onClose }) => { defaultMessage="Read our {docsLink} or go to our {forumLink} for questions or feedback." values={{ docsLink: ( - + = ({ fleetServerHosts, }) => { const { platform, setPlatform } = usePlatform(); + const { docLinks } = useStartServices(); const enrollArgs = getfleetServerHostsEnrollArgs(apiKey, fleetServerHosts); @@ -85,11 +86,7 @@ export const ManualInstructions: React.FunctionComponent = ({ defaultMessage="See the {link} for RPM / DEB deploy instructions." values={{ link: ( - + = ({ defaultMessage="If you are having trouble connecting, see our {link}." values={{ link: ( - + void) { } export const SettingFlyout: React.FunctionComponent = ({ onClose }) => { + const { docLinks } = useStartServices(); + const settingsRequest = useGetSettings(); const settings = settingsRequest?.data?.item; const outputsRequest = useGetOutputs(); @@ -302,7 +304,7 @@ export const SettingFlyout: React.FunctionComponent = ({ onClose }) => { values={{ link: ( diff --git a/x-pack/plugins/fleet/public/hooks/use_core.ts b/x-pack/plugins/fleet/public/hooks/use_core.ts index be4a21a094bd44..2c817bfc938f80 100644 --- a/x-pack/plugins/fleet/public/hooks/use_core.ts +++ b/x-pack/plugins/fleet/public/hooks/use_core.ts @@ -13,5 +13,6 @@ export function useStartServices(): FleetStartServices { if (services === null) { throw new Error('KibanaContextProvider not initialized'); } + return services; } diff --git a/x-pack/plugins/fleet/server/services/agents/helpers.ts b/x-pack/plugins/fleet/server/services/agents/helpers.ts index 822a2a9df98d5e..2618aad38bfbf3 100644 --- a/x-pack/plugins/fleet/server/services/agents/helpers.ts +++ b/x-pack/plugins/fleet/server/services/agents/helpers.ts @@ -7,7 +7,7 @@ import type { estypes } from '@elastic/elasticsearch'; -import type { SearchHit } from '../../../../../../typings/elasticsearch'; +import type { SearchHit } from '../../../../../../src/core/types/elasticsearch'; import type { Agent, AgentSOAttributes, FleetServerAgent } from '../../types'; type FleetServerAgentESResponse = diff --git a/x-pack/plugins/fleet/server/services/api_keys/enrollment_api_key.ts b/x-pack/plugins/fleet/server/services/api_keys/enrollment_api_key.ts index f9aab997f063c6..8f575f4969cf47 100644 --- a/x-pack/plugins/fleet/server/services/api_keys/enrollment_api_key.ts +++ b/x-pack/plugins/fleet/server/services/api_keys/enrollment_api_key.ts @@ -12,7 +12,7 @@ import { ResponseError } from '@elastic/elasticsearch/lib/errors'; import type { SavedObjectsClientContract, ElasticsearchClient } from 'src/core/server'; import { esKuery } from '../../../../../../src/plugins/data/server'; -import type { ESSearchResponse as SearchResponse } from '../../../../../../typings/elasticsearch'; +import type { ESSearchResponse as SearchResponse } from '../../../../../../src/core/types/elasticsearch'; import type { EnrollmentAPIKey, FleetServerEnrollmentAPIKey } from '../../types'; import { IngestManagerError } from '../../errors'; import { ENROLLMENT_API_KEYS_INDEX } from '../../constants'; diff --git a/x-pack/plugins/fleet/server/services/artifacts/mappings.ts b/x-pack/plugins/fleet/server/services/artifacts/mappings.ts index 79d14a27fa8271..10dab0400d5aa9 100644 --- a/x-pack/plugins/fleet/server/services/artifacts/mappings.ts +++ b/x-pack/plugins/fleet/server/services/artifacts/mappings.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { SearchHit } from '../../../../../../typings/elasticsearch'; +import type { SearchHit } from '../../../../../../src/core/types/elasticsearch'; import type { Artifact, ArtifactElasticsearchProperties, NewArtifact } from './types'; import { ARTIFACT_DOWNLOAD_RELATIVE_PATH } from './constants'; diff --git a/x-pack/plugins/fleet/server/services/artifacts/mocks.ts b/x-pack/plugins/fleet/server/services/artifacts/mocks.ts index 1a10f93f678b3f..8bc1768da23a2d 100644 --- a/x-pack/plugins/fleet/server/services/artifacts/mocks.ts +++ b/x-pack/plugins/fleet/server/services/artifacts/mocks.ts @@ -10,7 +10,7 @@ import type { ApiResponse } from '@elastic/elasticsearch'; import { ResponseError } from '@elastic/elasticsearch/lib/errors'; import { elasticsearchServiceMock } from '../../../../../../src/core/server/mocks'; -import type { SearchHit, ESSearchResponse } from '../../../../../../typings/elasticsearch'; +import type { SearchHit, ESSearchResponse } from '../../../../../../src/core/types/elasticsearch'; import type { Artifact, ArtifactElasticsearchProperties, ArtifactsClientInterface } from './types'; import { newArtifactToElasticsearchProperties } from './mappings'; diff --git a/x-pack/plugins/lens/server/routes/field_stats.ts b/x-pack/plugins/lens/server/routes/field_stats.ts index ef1043ddd3583f..12d3ef3f4a95e7 100644 --- a/x-pack/plugins/lens/server/routes/field_stats.ts +++ b/x-pack/plugins/lens/server/routes/field_stats.ts @@ -10,7 +10,7 @@ import { schema } from '@kbn/config-schema'; import { CoreSetup } from 'src/core/server'; import { IFieldType } from 'src/plugins/data/common'; import { SavedObjectNotFound } from '../../../../../src/plugins/kibana_utils/common'; -import { ESSearchResponse } from '../../../../../typings/elasticsearch'; +import { ESSearchResponse } from '../../../../../src/core/types/elasticsearch'; import { FieldStatsResponse, BASE_API_URL } from '../../common'; import { PluginStartContract } from '../plugin'; diff --git a/x-pack/plugins/lens/server/usage/task.ts b/x-pack/plugins/lens/server/usage/task.ts index 9c9ab7fd0b350f..9227ca885359bb 100644 --- a/x-pack/plugins/lens/server/usage/task.ts +++ b/x-pack/plugins/lens/server/usage/task.ts @@ -16,7 +16,7 @@ import { } from '../../../task_manager/server'; import { getVisualizationCounts } from './visualization_counts'; -import { ESSearchResponse } from '../../../../../typings/elasticsearch'; +import { ESSearchResponse } from '../../../../../src/core/types/elasticsearch'; // This task is responsible for running daily and aggregating all the Lens click event objects // into daily rolled-up documents, which will be used in reporting click stats diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/report_definition_field.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/report_definition_field.tsx index a4c4b4d1c78c0c..d36e33f16424c5 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/report_definition_field.tsx +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/report_definition_field.tsx @@ -11,7 +11,7 @@ import { isEmpty } from 'lodash'; import FieldValueSuggestions from '../../../field_value_suggestions'; import { useSeriesStorage } from '../../hooks/use_series_storage'; import { useAppIndexPatternContext } from '../../hooks/use_app_index_pattern'; -import { ESFilter } from '../../../../../../../../../typings/elasticsearch'; +import { ESFilter } from '../../../../../../../../../src/core/types/elasticsearch'; import { PersistableFilter } from '../../../../../../../lens/common'; import { ExistsFilter } from '../../../../../../../../../src/plugins/data/common/es_query/filters'; import { buildPhrasesFilter } from '../../configurations/utils'; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_expanded.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_expanded.tsx index 17d62b68c57e46..a78f6adeca39fc 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_expanded.tsx +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_expanded.tsx @@ -18,7 +18,7 @@ import { DataSeries, UrlFilter } from '../../types'; import { FilterValueButton } from './filter_value_btn'; import { useValuesList } from '../../../../../hooks/use_values_list'; import { euiStyled } from '../../../../../../../../../src/plugins/kibana_react/common'; -import { ESFilter } from '../../../../../../../../../typings/elasticsearch'; +import { ESFilter } from '../../../../../../../../../src/core/types/elasticsearch'; import { PersistableFilter } from '../../../../../../../lens/common'; import { ExistsFilter } from '../../../../../../../../../src/plugins/data/common/es_query/filters'; diff --git a/x-pack/plugins/observability/public/components/shared/field_value_suggestions/types.ts b/x-pack/plugins/observability/public/components/shared/field_value_suggestions/types.ts index 48745c5a8f8a69..ab24f4064c02e5 100644 --- a/x-pack/plugins/observability/public/components/shared/field_value_suggestions/types.ts +++ b/x-pack/plugins/observability/public/components/shared/field_value_suggestions/types.ts @@ -7,7 +7,7 @@ import { PopoverAnchorPosition } from '@elastic/eui'; import { Dispatch, SetStateAction } from 'react'; -import { ESFilter } from 'typings/elasticsearch'; +import { ESFilter } from 'src/core/types/elasticsearch'; interface CommonProps { selectedValue?: string[]; diff --git a/x-pack/plugins/observability/public/hooks/use_es_search.ts b/x-pack/plugins/observability/public/hooks/use_es_search.ts index 18a846a6f85d2b..27c4081a99775f 100644 --- a/x-pack/plugins/observability/public/hooks/use_es_search.ts +++ b/x-pack/plugins/observability/public/hooks/use_es_search.ts @@ -7,7 +7,7 @@ import { estypes } from '@elastic/elasticsearch'; import { DataPublicPluginStart } from '../../../../../src/plugins/data/public'; -import { ESSearchResponse } from '../../../../../typings/elasticsearch'; +import { ESSearchResponse } from '../../../../../src/core/types/elasticsearch'; import { useKibana } from '../../../../../src/plugins/kibana_react/public'; import { isCompleteResponse } from '../../../../../src/plugins/data/common'; import { useFetcher } from './use_fetcher'; diff --git a/x-pack/plugins/observability/public/hooks/use_values_list.ts b/x-pack/plugins/observability/public/hooks/use_values_list.ts index e563293d26d6f9..094b7a0f369213 100644 --- a/x-pack/plugins/observability/public/hooks/use_values_list.ts +++ b/x-pack/plugins/observability/public/hooks/use_values_list.ts @@ -8,7 +8,7 @@ import { capitalize, union } from 'lodash'; import { useEffect, useState } from 'react'; import useDebounce from 'react-use/lib/useDebounce'; -import { ESFilter } from '../../../../../typings/elasticsearch'; +import { ESFilter } from '../../../../../src/core/types/elasticsearch'; import { createEsParams, useEsSearch } from './use_es_search'; export interface Props { diff --git a/x-pack/plugins/rule_registry/server/rule_data_client/types.ts b/x-pack/plugins/rule_registry/server/rule_data_client/types.ts index 348fca6a58188e..d5ce022781b0d0 100644 --- a/x-pack/plugins/rule_registry/server/rule_data_client/types.ts +++ b/x-pack/plugins/rule_registry/server/rule_data_client/types.ts @@ -9,7 +9,7 @@ import { ApiResponse } from '@elastic/elasticsearch'; import { BulkRequest, BulkResponse } from '@elastic/elasticsearch/api/types'; import { ElasticsearchClient } from 'kibana/server'; import { FieldDescriptor } from 'src/plugins/data/server'; -import { ESSearchRequest, ESSearchResponse } from 'typings/elasticsearch'; +import { ESSearchRequest, ESSearchResponse } from 'src/core/types/elasticsearch'; import { TechnicalRuleDataFieldName } from '../../common/technical_rule_data_field_names'; export interface RuleDataReader { diff --git a/x-pack/plugins/rule_registry/server/utils/create_persistence_rule_type_factory.ts b/x-pack/plugins/rule_registry/server/utils/create_persistence_rule_type_factory.ts index 0e244fbaa2ee35..3f50b78151e741 100644 --- a/x-pack/plugins/rule_registry/server/utils/create_persistence_rule_type_factory.ts +++ b/x-pack/plugins/rule_registry/server/utils/create_persistence_rule_type_factory.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { ESSearchRequest } from 'typings/elasticsearch'; +import { ESSearchRequest } from 'src/core/types/elasticsearch'; import v4 from 'uuid/v4'; import { Logger } from '@kbn/logging'; diff --git a/x-pack/plugins/security_solution/public/common/components/endpoint/agent_status.tsx b/x-pack/plugins/security_solution/public/common/components/endpoint/agent_status.tsx new file mode 100644 index 00000000000000..f93721349fdac0 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/agent_status.tsx @@ -0,0 +1,30 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { EuiBadge } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { HostStatus } from '../../../../common/endpoint/types'; +import { HOST_STATUS_TO_BADGE_COLOR } from '../../../management/pages/endpoint_hosts/view/host_constants'; + +export const AgentStatus = React.memo(({ hostStatus }: { hostStatus: HostStatus }) => { + return ( + + + + ); +}); + +AgentStatus.displayName = 'AgentStatus'; diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/alert_summary_view.tsx b/x-pack/plugins/security_solution/public/common/components/event_details/alert_summary_view.tsx index 5578264152c39a..e229c0c6fae493 100644 --- a/x-pack/plugins/security_solution/public/common/components/event_details/alert_summary_view.tsx +++ b/x-pack/plugins/security_solution/public/common/components/event_details/alert_summary_view.tsx @@ -12,7 +12,7 @@ import { EuiDescriptionListTitle, EuiSpacer, } from '@elastic/eui'; -import { get, getOr } from 'lodash/fp'; +import { get, getOr, find } from 'lodash/fp'; import React, { useMemo } from 'react'; import styled from 'styled-components'; @@ -53,6 +53,7 @@ const fields = [ { id: 'signal.rule.severity', label: ALERTS_HEADERS_SEVERITY }, { id: 'signal.rule.risk_score', label: ALERTS_HEADERS_RISK_SCORE }, { id: 'host.name' }, + { id: 'host.status' }, { id: 'user.name' }, { id: SOURCE_IP_FIELD_NAME, fieldType: IP_FIELD_TYPE }, { id: DESTINATION_IP_FIELD_NAME, fieldType: IP_FIELD_TYPE }, @@ -177,6 +178,24 @@ const AlertSummaryViewComponent: React.FC<{ timelineId, ]); + const agentId = useMemo(() => { + const findAgentId = find({ category: 'agent', field: 'agent.id' }, data)?.values; + return findAgentId ? findAgentId[0] : ''; + }, [data]); + + const agentStatusRow = { + title: i18n.AGENT_STATUS, + description: { + contextId: timelineId, + eventId, + fieldName: 'host.status', + value: agentId, + linkValue: undefined, + }, + }; + + const summaryRowsWithAgentStatus = [...summaryRows, agentStatusRow]; + const ruleId = useMemo(() => { const item = data.find((d) => d.field === 'signal.rule.id'); return Array.isArray(item?.originalValue) @@ -188,7 +207,11 @@ const AlertSummaryViewComponent: React.FC<{ return ( <> - + {maybeRule?.note && ( {i18n.INVESTIGATION_GUIDE} diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/translations.ts b/x-pack/plugins/security_solution/public/common/components/event_details/translations.ts index 1ff88d9c2018b9..a28d1976ca9400 100644 --- a/x-pack/plugins/security_solution/public/common/components/event_details/translations.ts +++ b/x-pack/plugins/security_solution/public/common/components/event_details/translations.ts @@ -99,3 +99,7 @@ export const NESTED_COLUMN = (field: string) => defaultMessage: 'The {field} field is an object, and is broken down into nested fields which can be added as column', }); + +export const AGENT_STATUS = i18n.translate('xpack.securitySolution.detections.alerts.agentStatus', { + defaultMessage: 'Agent status', +}); diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/api.ts b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/api.ts index 71eac547dcc8eb..05706981a681dc 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/api.ts +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/api.ts @@ -7,7 +7,7 @@ import { UpdateDocumentByQueryResponse } from 'elasticsearch'; import { getCasesFromAlertsUrl } from '../../../../../../cases/common'; -import { HostIsolationResponse, HostMetadataInfo } from '../../../../../common/endpoint/types'; +import { HostIsolationResponse, HostInfo } from '../../../../../common/endpoint/types'; import { DETECTION_ENGINE_QUERY_SIGNALS_URL, DETECTION_ENGINE_SIGNALS_STATUS_URL, @@ -178,12 +178,8 @@ export const getCaseIdsFromAlertId = async ({ * * @param host id */ -export const getHostMetadata = async ({ - agentId, -}: { - agentId: string; -}): Promise => - KibanaServices.get().http.fetch( +export const getHostMetadata = async ({ agentId }: { agentId: string }): Promise => + KibanaServices.get().http.fetch( resolvePathVariables(HOST_METADATA_GET_ROUTE, { id: agentId }), { method: 'get' } ); diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_host_isolation_status.tsx b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_host_isolation_status.tsx index f7894d47642755..7419727fff6a2a 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_host_isolation_status.tsx +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_host_isolation_status.tsx @@ -7,25 +7,27 @@ import { isEmpty } from 'lodash'; import { useEffect, useState } from 'react'; -import { Maybe } from '../../../../../../observability/common/typings'; import { useAppToasts } from '../../../../common/hooks/use_app_toasts'; import { getHostMetadata } from './api'; import { ISOLATION_STATUS_FAILURE } from './translations'; import { isEndpointHostIsolated } from '../../../../common/utils/validators'; +import { HostStatus } from '../../../../../common/endpoint/types'; interface HostIsolationStatusResponse { loading: boolean; - isIsolated: Maybe; + isIsolated: boolean; + agentStatus: HostStatus; } /* - * Retrieves the current isolation status of a host */ + * Retrieves the current isolation status of a host and the agent/host status */ export const useHostIsolationStatus = ({ agentId, }: { agentId: string; }): HostIsolationStatusResponse => { - const [isIsolated, setIsIsolated] = useState>(); + const [isIsolated, setIsIsolated] = useState(false); + const [agentStatus, setAgentStatus] = useState(HostStatus.UNHEALTHY); const [loading, setLoading] = useState(false); const { addError } = useAppToasts(); @@ -38,6 +40,7 @@ export const useHostIsolationStatus = ({ const metadataResponse = await getHostMetadata({ agentId }); if (isMounted) { setIsIsolated(isEndpointHostIsolated(metadataResponse.metadata)); + setAgentStatus(metadataResponse.host_status); } } catch (error) { addError(error.message, { title: ISOLATION_STATUS_FAILURE }); @@ -61,5 +64,5 @@ export const useHostIsolationStatus = ({ isMounted = false; }; }, [addError, agentId]); - return { loading, isIsolated }; + return { loading, isIsolated, agentStatus }; }; diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/agent_statuses.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/agent_statuses.tsx new file mode 100644 index 00000000000000..16f11809dd72b5 --- /dev/null +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/agent_statuses.tsx @@ -0,0 +1,56 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { DefaultDraggable } from '../../../../../common/components/draggables'; +import { EndpointHostIsolationStatus } from '../../../../../common/components/endpoint/host_isolation'; +import { useHostIsolationStatus } from '../../../../../detections/containers/detection_engine/alerts/use_host_isolation_status'; +import { AgentStatus } from '../../../../../common/components/endpoint/agent_status'; + +export const AgentStatuses = React.memo( + ({ + fieldName, + contextId, + eventId, + value, + }: { + fieldName: string; + contextId: string; + eventId: string; + value: string; + }) => { + const { isIsolated, agentStatus } = useHostIsolationStatus({ agentId: value }); + const isolationFieldName = 'host.isolation'; + return ( + + + + + + + + + + + + + ); + } +); + +AgentStatuses.displayName = 'AgentStatuses'; diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/constants.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/constants.tsx index b1ef634fe052f1..761d82b482af2e 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/constants.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/constants.tsx @@ -16,3 +16,4 @@ export const REFERENCE_URL_FIELD_NAME = 'reference.url'; export const EVENT_URL_FIELD_NAME = 'event.url'; export const SIGNAL_RULE_NAME_FIELD_NAME = 'signal.rule.name'; export const SIGNAL_STATUS_FIELD_NAME = 'signal.status'; +export const HOST_STATUS_FIELD_NAME = 'host.status'; diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/formatted_field.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/formatted_field.tsx index 12effcd3fa81fb..efb51916e37653 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/formatted_field.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/formatted_field.tsx @@ -5,6 +5,8 @@ * 2.0. */ +/* eslint-disable complexity */ + import { EuiFlexGroup, EuiFlexItem, EuiToolTip } from '@elastic/eui'; import { isNumber, isEmpty } from 'lodash/fp'; import React from 'react'; @@ -30,11 +32,13 @@ import { REFERENCE_URL_FIELD_NAME, EVENT_URL_FIELD_NAME, SIGNAL_STATUS_FIELD_NAME, + HOST_STATUS_FIELD_NAME, GEO_FIELD_TYPE, } from './constants'; import { RenderRuleName, renderEventModule, renderUrl } from './formatted_field_helpers'; import { RuleStatus } from './rule_status'; import { HostName } from './host_name'; +import { AgentStatuses } from './agent_statuses'; // simple black-list to prevent dragging and dropping fields such as message name const columnNamesNotDraggable = [MESSAGE_FIELD_NAME]; @@ -116,6 +120,15 @@ const FormattedFieldValueComponent: React.FC<{ return ( ); + } else if (fieldName === HOST_STATUS_FIELD_NAME) { + return ( + + ); } else if ( [ RULE_REFERENCE_FIELD_NAME, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/reference_rules/query.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/reference_rules/query.ts index 04bfa78f883f01..39f325fd6cf8f1 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/reference_rules/query.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/reference_rules/query.ts @@ -8,7 +8,7 @@ import type { estypes } from '@elastic/elasticsearch'; import { schema } from '@kbn/config-schema'; import { Logger } from '@kbn/logging'; -import { ESSearchRequest } from 'typings/elasticsearch'; +import { ESSearchRequest } from 'src/core/types/elasticsearch'; import { buildEsQuery, IIndexPattern } from '../../../../../../../src/plugins/data/common'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/get_threshold_bucket_filters.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/get_threshold_bucket_filters.ts index 4dd21938690dba..e6a188a20b5d5d 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/get_threshold_bucket_filters.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/get_threshold_bucket_filters.ts @@ -6,7 +6,7 @@ */ import { Filter } from 'src/plugins/data/common'; -import { ESFilter } from '../../../../../../../../typings/elasticsearch'; +import { ESFilter } from '../../../../../../../../src/core/types/elasticsearch'; import { ThresholdSignalHistory, ThresholdSignalHistoryRecord } from '../types'; export const getThresholdBucketFilters = async ({ diff --git a/x-pack/plugins/security_solution/server/lib/machine_learning/index.test.ts b/x-pack/plugins/security_solution/server/lib/machine_learning/index.test.ts index 30dd5adf6123bd..41f68337437976 100644 --- a/x-pack/plugins/security_solution/server/lib/machine_learning/index.test.ts +++ b/x-pack/plugins/security_solution/server/lib/machine_learning/index.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ESFilter } from '../../../../../../typings/elasticsearch'; +import { ESFilter } from '../../../../../../src/core/types/elasticsearch'; import { getExceptionListItemSchemaMock } from '../../../../lists/common/schemas/response/exception_list_item_schema.mock'; import { getAnomalies, AnomaliesSearchParams } from '.'; diff --git a/x-pack/plugins/stack_alerts/common/build_sorted_events_query.ts b/x-pack/plugins/stack_alerts/common/build_sorted_events_query.ts index 455307cb73a097..83421056229cf5 100644 --- a/x-pack/plugins/stack_alerts/common/build_sorted_events_query.ts +++ b/x-pack/plugins/stack_alerts/common/build_sorted_events_query.ts @@ -5,7 +5,7 @@ * 2.0. */ import { estypes } from '@elastic/elasticsearch'; -import type { ESSearchRequest } from '../../../../typings/elasticsearch'; +import type { ESSearchRequest } from '../../../../src/core/types/elasticsearch'; interface BuildSortedEventsQueryOpts { aggs?: Record; diff --git a/x-pack/plugins/stack_alerts/server/alert_types/es_query/alert_type.test.ts b/x-pack/plugins/stack_alerts/server/alert_types/es_query/alert_type.test.ts index d195534d93f582..5b450ceba192a6 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/es_query/alert_type.test.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/es_query/alert_type.test.ts @@ -17,7 +17,7 @@ import { loggingSystemMock } from '../../../../../../src/core/server/mocks'; import { getAlertType, ConditionMetAlertInstanceId, ActionGroupId } from './alert_type'; import { EsQueryAlertParams, EsQueryAlertState } from './alert_type_params'; import { ActionContext } from './action_context'; -import { ESSearchResponse, ESSearchRequest } from '../../../../../../typings/elasticsearch'; +import { ESSearchResponse, ESSearchRequest } from '../../../../../../src/core/types/elasticsearch'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { elasticsearchClientMock } from '../../../../../../src/core/server/elasticsearch/client/mocks'; diff --git a/x-pack/plugins/task_manager/server/monitoring/workload_statistics.ts b/x-pack/plugins/task_manager/server/monitoring/workload_statistics.ts index abd86be522f0cd..64c1c661401963 100644 --- a/x-pack/plugins/task_manager/server/monitoring/workload_statistics.ts +++ b/x-pack/plugins/task_manager/server/monitoring/workload_statistics.ts @@ -13,7 +13,7 @@ import { keyBy, mapValues } from 'lodash'; import { estypes } from '@elastic/elasticsearch'; import { AggregatedStatProvider } from './runtime_statistics_aggregator'; import { parseIntervalAsSecond, asInterval, parseIntervalAsMillisecond } from '../lib/intervals'; -import { AggregationResultOf } from '../../../../../typings/elasticsearch'; +import { AggregationResultOf } from '../../../../../src/core/types/elasticsearch'; import { HealthStatus } from './monitoring_stats_stream'; import { TaskStore } from '../task_store'; import { createRunningAveragedStat } from './task_run_calcultors'; diff --git a/x-pack/plugins/uptime/server/lib/lib.ts b/x-pack/plugins/uptime/server/lib/lib.ts index e79d3c28a7d3a7..cf008413135367 100644 --- a/x-pack/plugins/uptime/server/lib/lib.ts +++ b/x-pack/plugins/uptime/server/lib/lib.ts @@ -17,7 +17,7 @@ import { UMBackendFrameworkAdapter } from './adapters'; import { UMLicenseCheck } from './domains'; import { UptimeRequests } from './requests'; import { savedObjectsAdapter } from './saved_objects'; -import { ESSearchResponse } from '../../../../../typings/elasticsearch'; +import { ESSearchResponse } from '../../../../../src/core/types/elasticsearch'; export interface UMDomainLibs { requests: UptimeRequests; diff --git a/x-pack/plugins/uptime/server/lib/requests/get_journey_failed_steps.ts b/x-pack/plugins/uptime/server/lib/requests/get_journey_failed_steps.ts index d14a723d27628d..d98e2354601676 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_journey_failed_steps.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_journey_failed_steps.ts @@ -6,7 +6,7 @@ */ import { QueryDslQueryContainer } from '@elastic/elasticsearch/api/types'; -import { SearchHit } from '../../../../../../typings/elasticsearch'; +import { SearchHit } from '../../../../../../src/core/types/elasticsearch'; import { asMutableArray } from '../../../common/utils/as_mutable_array'; import { UMElasticsearchQueryFn } from '../adapters/framework'; import { Ping } from '../../../common/runtime_types'; diff --git a/x-pack/plugins/uptime/server/lib/requests/get_journey_steps.ts b/x-pack/plugins/uptime/server/lib/requests/get_journey_steps.ts index 2e32670aea276a..95aadc776fa765 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_journey_steps.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_journey_steps.ts @@ -6,7 +6,7 @@ */ import { QueryDslQueryContainer } from '@elastic/elasticsearch/api/types'; -import { SearchHit } from 'typings/elasticsearch/search'; +import { SearchHit } from 'src/core/types/elasticsearch/search'; import { asMutableArray } from '../../../common/utils/as_mutable_array'; import { UMElasticsearchQueryFn } from '../adapters/framework'; import { Ping } from '../../../common/runtime_types'; diff --git a/x-pack/plugins/uptime/server/lib/requests/get_snapshot_counts.ts b/x-pack/plugins/uptime/server/lib/requests/get_snapshot_counts.ts index 0e47f2a3d56c29..aef01f29f4d576 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_snapshot_counts.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_snapshot_counts.ts @@ -9,7 +9,7 @@ import { UMElasticsearchQueryFn } from '../adapters'; import { CONTEXT_DEFAULTS } from '../../../common/constants'; import { Snapshot } from '../../../common/runtime_types'; import { QueryContext } from './search'; -import { ESFilter } from '../../../../../../typings/elasticsearch'; +import { ESFilter } from '../../../../../../src/core/types/elasticsearch'; export interface GetSnapshotCountParams { dateRangeStart: string; diff --git a/x-pack/plugins/uptime/server/lib/requests/search/query_context.ts b/x-pack/plugins/uptime/server/lib/requests/search/query_context.ts index b54515e84289a3..d443411ef4c6e7 100644 --- a/x-pack/plugins/uptime/server/lib/requests/search/query_context.ts +++ b/x-pack/plugins/uptime/server/lib/requests/search/query_context.ts @@ -10,7 +10,7 @@ import { CursorPagination } from './types'; import { parseRelativeDate } from '../../helper'; import { CursorDirection, SortOrder } from '../../../../common/runtime_types'; import { UptimeESClient } from '../../lib'; -import { ESFilter } from '../../../../../../../typings/elasticsearch'; +import { ESFilter } from '../../../../../../../src/core/types/elasticsearch'; export class QueryContext { callES: UptimeESClient; diff --git a/x-pack/test/functional/apps/dashboard_mode/dashboard_empty_screen.js b/x-pack/test/functional/apps/dashboard_mode/dashboard_empty_screen.js index 96c40bc4cf4097..2adf13db26250d 100644 --- a/x-pack/test/functional/apps/dashboard_mode/dashboard_empty_screen.js +++ b/x-pack/test/functional/apps/dashboard_mode/dashboard_empty_screen.js @@ -13,7 +13,8 @@ export default function ({ getPageObjects, getService }) { const dashboardPanelActions = getService('dashboardPanelActions'); const PageObjects = getPageObjects(['common', 'dashboard', 'visualize', 'lens']); - describe('empty dashboard', function () { + // FLAKY: https://github.com/elastic/kibana/issues/102366 + describe.skip('empty dashboard', function () { before(async () => { await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/logstash_functional'); await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/lens/basic'); diff --git a/x-pack/test/functional/apps/lens/formula.ts b/x-pack/test/functional/apps/lens/formula.ts index db7c680ac20af6..d1376731886eb8 100644 --- a/x-pack/test/functional/apps/lens/formula.ts +++ b/x-pack/test/functional/apps/lens/formula.ts @@ -15,7 +15,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const browser = getService('browser'); const testSubjects = getService('testSubjects'); - describe('lens formula', () => { + // FLAKY: https://github.com/elastic/kibana/issues/102183 + describe.skip('lens formula', () => { it('should transition from count to formula', async () => { await PageObjects.visualize.gotoVisualizationLandingPage(); await listingTable.searchForItemWithName('lnsXYvis'); diff --git a/x-pack/test/functional/apps/ml/anomaly_detection/date_nanos_job.ts b/x-pack/test/functional/apps/ml/anomaly_detection/date_nanos_job.ts index 024735e9390247..d351e8f7057e4b 100644 --- a/x-pack/test/functional/apps/ml/anomaly_detection/date_nanos_job.ts +++ b/x-pack/test/functional/apps/ml/anomaly_detection/date_nanos_job.ts @@ -123,8 +123,6 @@ export default function ({ getService }: FtrProviderContext) { '@timestamp' ); await ml.testResources.setKibanaTimeZoneToUTC(); - - await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/ml/event_rate_nanos'); await ml.securityUI.loginAsMlPowerUser(); }); diff --git a/x-pack/test/functional/apps/reporting/reporting.ts b/x-pack/test/functional/apps/reporting/reporting.ts index bd1626ec32380e..9896e3371a2822 100644 --- a/x-pack/test/functional/apps/reporting/reporting.ts +++ b/x-pack/test/functional/apps/reporting/reporting.ts @@ -13,7 +13,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const es = getService('es'); const esArchiver = getService('esArchiver'); - describe('Reporting', function () { + // FLAKY: https://github.com/elastic/kibana/issues/102722 + describe.skip('Reporting', function () { this.tags(['smoke', 'ciGroup2']); before(async () => { await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/packaging'); diff --git a/x-pack/test/saved_object_api_integration/common/suites/export.ts b/x-pack/test/saved_object_api_integration/common/suites/export.ts index d9ebbac8102315..ea2f321458c222 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/export.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/export.ts @@ -21,12 +21,15 @@ const { export interface ExportTestDefinition extends TestDefinition { request: ReturnType; } + export type ExportTestSuite = TestSuite; + interface SuccessResult { type: string; id: string; originId?: string; } + export interface ExportTestCase { title: string; type: string; @@ -135,7 +138,13 @@ export const createRequest = ({ type, id }: ExportTestCase) => const getTestTitle = ({ failure, title }: ExportTestCase) => `${failure?.reason || 'success'} ["${title}"]`; -const EMPTY_RESULT = { exportedCount: 0, missingRefCount: 0, missingReferences: [] }; +const EMPTY_RESULT = { + excludedObjects: [], + excludedObjectsCount: 0, + exportedCount: 0, + missingRefCount: 0, + missingReferences: [], +}; export function exportTestSuiteFactory(esArchiver: any, supertest: SuperTest) { const expectSavedObjectForbiddenBulkGet = expectResponses.forbiddenTypes('bulk_get'); @@ -189,6 +198,8 @@ export function exportTestSuiteFactory(esArchiver: any, supertest: SuperTest