diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 96670b5d5107b..6da2d5d602186 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -136,7 +136,7 @@ # Observability UIs /x-pack/plugins/infra/ @elastic/logs-metrics-ui -/x-pack/plugins/ingest_manager/ @elastic/ingest-management +/x-pack/plugins/fleet/ @elastic/ingest-management /x-pack/plugins/observability/ @elastic/observability-ui /x-pack/plugins/monitoring/ @elastic/stack-monitoring-ui /x-pack/plugins/uptime @elastic/uptime @@ -254,9 +254,6 @@ /x-pack/test/ui_capabilities/ @elastic/kibana-security /x-pack/test/encrypted_saved_objects_api_integration/ @elastic/kibana-security /x-pack/test/functional/apps/security/ @elastic/kibana-security -/x-pack/test/kerberos_api_integration/ @elastic/kibana-security -/x-pack/test/oidc_api_integration/ @elastic/kibana-security -/x-pack/test/pki_api_integration/ @elastic/kibana-security /x-pack/test/security_api_integration/ @elastic/kibana-security /x-pack/test/security_functional/ @elastic/kibana-security /x-pack/test/spaces_api_integration/ @elastic/kibana-security @@ -302,6 +299,8 @@ x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json @elastic/kib /x-pack/plugins/triggers_actions_ui/ @elastic/kibana-alerting-services /x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/ @elastic/kibana-alerting-services /x-pack/test/functional_with_es_ssl/fixtures/plugins/alerts/ @elastic/kibana-alerting-services +/docs/user/alerting/ @elastic/kibana-alerting-services +/docs/management/alerting/ @elastic/kibana-alerting-services #CC# /x-pack/legacy/plugins/actions/ @elastic/kibana-alerting-services #CC# /x-pack/legacy/plugins/alerting/ @elastic/kibana-alerting-services #CC# /x-pack/legacy/plugins/task_manager @elastic/kibana-alerting-services @@ -380,7 +379,7 @@ x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json @elastic/kib # Observability design /x-pack/plugins/apm/**/*.scss @elastic/observability-design /x-pack/plugins/infra/**/*.scss @elastic/observability-design -/x-pack/plugins/ingest_manager/**/*.scss @elastic/observability-design +/x-pack/plugins/fleet/**/*.scss @elastic/observability-design /x-pack/plugins/observability/**/*.scss @elastic/observability-design /x-pack/plugins/monitoring/**/*.scss @elastic/observability-design diff --git a/.github/ISSUE_TEMPLATE/v8_breaking_change.md b/.github/ISSUE_TEMPLATE/v8_breaking_change.md index a64ce33b8f976..86e321990d05f 100644 --- a/.github/ISSUE_TEMPLATE/v8_breaking_change.md +++ b/.github/ISSUE_TEMPLATE/v8_breaking_change.md @@ -30,6 +30,8 @@ requesting the breaking change to be surfaced in the Upgrade Assistant. +**How can we programmatically determine whether the cluster is affected by this breaking change?** + **What can users do to address the change manually?** diff --git a/.github/paths-labeller.yml b/.github/paths-labeller.yml index 2e8529b4a7704..bd8427ea18d69 100644 --- a/.github/paths-labeller.yml +++ b/.github/paths-labeller.yml @@ -11,7 +11,7 @@ - "Team:apm": - "x-pack/plugins/apm/**/*.*" - "Team:Ingest Management": - - "x-pack/plugins/ingest_manager/**/*.*" + - "x-pack/plugins/fleet/**/*.*" - "x-pack/test/api_integration/apis/fleet/**/*.*" - "x-pack/test/epm_api_integration/**/*.*" - "Team:uptime": diff --git a/config/kibana.yml b/config/kibana.yml index 58ae8b9346f51..ce9fe28dae916 100644 --- a/config/kibana.yml +++ b/config/kibana.yml @@ -80,7 +80,7 @@ #elasticsearch.logQueries: false # Specifies the path where Kibana creates the process ID file. -#pid.file: /var/run/kibana.pid +#pid.file: /run/kibana/kibana.pid # Enables you to specify a file where Kibana stores log output. #logging.dest: stdout diff --git a/docs/developer/plugin-list.asciidoc b/docs/developer/plugin-list.asciidoc index 3c62c1fbca982..e89b6d86361c7 100644 --- a/docs/developer/plugin-list.asciidoc +++ b/docs/developer/plugin-list.asciidoc @@ -413,7 +413,7 @@ Index Management by running this series of requests in Console: the infrastructure monitoring use-case within Kibana. -|{kib-repo}blob/{branch}/x-pack/plugins/ingest_manager/README.md[ingestManager] +|{kib-repo}blob/{branch}/x-pack/plugins/fleet/README.md[ingestManager] |Fleet needs to have Elasticsearch API keys enabled, and also to have TLS enabled on kibana, (if you want to run Kibana without TLS you can provide the following config flag --xpack.fleet.agents.tlsCheckDisabled=false) diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.executioncontextsearch.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.executioncontextsearch.md new file mode 100644 index 0000000000000..67dcb2fa44241 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.executioncontextsearch.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [ExecutionContextSearch](./kibana-plugin-plugins-data-public.executioncontextsearch.md) + +## ExecutionContextSearch type + +Signature: + +```typescript +export declare type ExecutionContextSearch = { + filters?: Filter[]; + query?: Query | Query[]; + timeRange?: TimeRange; +}; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.expressionfunctionkibana.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.expressionfunctionkibana.md new file mode 100644 index 0000000000000..c91f2e8144ead --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.expressionfunctionkibana.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [ExpressionFunctionKibana](./kibana-plugin-plugins-data-public.expressionfunctionkibana.md) + +## ExpressionFunctionKibana type + +Signature: + +```typescript +export declare type ExpressionFunctionKibana = ExpressionFunctionDefinition<'kibana', ExpressionValueSearchContext | null, object, ExpressionValueSearchContext, ExecutionContext>; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.expressionfunctionkibanacontext.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.expressionfunctionkibanacontext.md new file mode 100644 index 0000000000000..97d2e81d45554 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.expressionfunctionkibanacontext.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [ExpressionFunctionKibanaContext](./kibana-plugin-plugins-data-public.expressionfunctionkibanacontext.md) + +## ExpressionFunctionKibanaContext type + +Signature: + +```typescript +export declare type ExpressionFunctionKibanaContext = ExpressionFunctionDefinition<'kibana_context', KibanaContext | null, Arguments, Promise, ExecutionContext>; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionvaluesearchcontext.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.expressionvaluesearchcontext.md similarity index 54% rename from docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionvaluesearchcontext.md rename to docs/development/plugins/data/public/kibana-plugin-plugins-data-public.expressionvaluesearchcontext.md index 6e38adde3ba91..4849d82b94a62 100644 --- a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionvaluesearchcontext.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.expressionvaluesearchcontext.md @@ -1,6 +1,6 @@ -[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionValueSearchContext](./kibana-plugin-plugins-expressions-server.expressionvaluesearchcontext.md) +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [ExpressionValueSearchContext](./kibana-plugin-plugins-data-public.expressionvaluesearchcontext.md) ## ExpressionValueSearchContext type diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.getfieldsforindexpattern.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.getfieldsforindexpattern.md index c06c3c6f68492..f288573cd7abb 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.getfieldsforindexpattern.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.getfieldsforindexpattern.md @@ -9,5 +9,5 @@ Get field list by providing an index patttern (or spec) Signature: ```typescript -getFieldsForIndexPattern: (indexPattern: IndexPattern | IndexPatternSpec, options?: GetFieldsOptions) => Promise; +getFieldsForIndexPattern: (indexPattern: IndexPattern | IndexPatternSpec, options?: GetFieldsOptions | undefined) => Promise; ``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.getfieldsforwildcard.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.getfieldsforwildcard.md index aec84866b9e58..32bf6fc13b02c 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.getfieldsforwildcard.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.getfieldsforwildcard.md @@ -9,5 +9,5 @@ Get field list by providing { pattern } Signature: ```typescript -getFieldsForWildcard: (options?: GetFieldsOptions) => Promise; +getFieldsForWildcard: (options: GetFieldsOptions) => Promise; ``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.md index 34df8656e9175..57bb98de09ebd 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.md @@ -26,8 +26,8 @@ export declare class IndexPatternsService | [get](./kibana-plugin-plugins-data-public.indexpatternsservice.get.md) | | (id: string) => Promise<IndexPattern> | Get an index pattern by id. Cache optimized | | [getCache](./kibana-plugin-plugins-data-public.indexpatternsservice.getcache.md) | | () => Promise<SavedObject<IndexPatternSavedObjectAttrs>[] | null | undefined> | | | [getDefault](./kibana-plugin-plugins-data-public.indexpatternsservice.getdefault.md) | | () => Promise<IndexPattern | null> | Get default index pattern | -| [getFieldsForIndexPattern](./kibana-plugin-plugins-data-public.indexpatternsservice.getfieldsforindexpattern.md) | | (indexPattern: IndexPattern | IndexPatternSpec, options?: GetFieldsOptions) => Promise<any> | Get field list by providing an index patttern (or spec) | -| [getFieldsForWildcard](./kibana-plugin-plugins-data-public.indexpatternsservice.getfieldsforwildcard.md) | | (options?: GetFieldsOptions) => Promise<any> | Get field list by providing { pattern } | +| [getFieldsForIndexPattern](./kibana-plugin-plugins-data-public.indexpatternsservice.getfieldsforindexpattern.md) | | (indexPattern: IndexPattern | IndexPatternSpec, options?: GetFieldsOptions | undefined) => Promise<any> | Get field list by providing an index patttern (or spec) | +| [getFieldsForWildcard](./kibana-plugin-plugins-data-public.indexpatternsservice.getfieldsforwildcard.md) | | (options: GetFieldsOptions) => Promise<any> | Get field list by providing { pattern } | | [getIds](./kibana-plugin-plugins-data-public.indexpatternsservice.getids.md) | | (refresh?: boolean) => Promise<string[]> | Get list of index pattern ids | | [getIdsWithTitle](./kibana-plugin-plugins-data-public.indexpatternsservice.getidswithtitle.md) | | (refresh?: boolean) => Promise<Array<{
id: string;
title: string;
}>> | Get list of index pattern ids with titles | | [getTitles](./kibana-plugin-plugins-data-public.indexpatternsservice.gettitles.md) | | (refresh?: boolean) => Promise<string[]> | Get list of index pattern titles | diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanacontext.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.kibanacontext.md similarity index 51% rename from docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanacontext.md rename to docs/development/plugins/data/public/kibana-plugin-plugins-data-public.kibanacontext.md index 108533e8de357..cb8842c66761d 100644 --- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanacontext.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.kibanacontext.md @@ -1,6 +1,6 @@ -[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [KibanaContext](./kibana-plugin-plugins-expressions-public.kibanacontext.md) +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [KibanaContext](./kibana-plugin-plugins-data-public.kibanacontext.md) ## KibanaContext type diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md index 255a9947858f6..bafcd8bdffff9 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md @@ -142,7 +142,11 @@ | [EsdslExpressionFunctionDefinition](./kibana-plugin-plugins-data-public.esdslexpressionfunctiondefinition.md) | | | [EsQuerySortValue](./kibana-plugin-plugins-data-public.esquerysortvalue.md) | | | [EsRawResponseExpressionTypeDefinition](./kibana-plugin-plugins-data-public.esrawresponseexpressiontypedefinition.md) | | +| [ExecutionContextSearch](./kibana-plugin-plugins-data-public.executioncontextsearch.md) | | | [ExistsFilter](./kibana-plugin-plugins-data-public.existsfilter.md) | | +| [ExpressionFunctionKibana](./kibana-plugin-plugins-data-public.expressionfunctionkibana.md) | | +| [ExpressionFunctionKibanaContext](./kibana-plugin-plugins-data-public.expressionfunctionkibanacontext.md) | | +| [ExpressionValueSearchContext](./kibana-plugin-plugins-data-public.expressionvaluesearchcontext.md) | | | [FieldFormatId](./kibana-plugin-plugins-data-public.fieldformatid.md) | id type is needed for creating custom converters. | | [FieldFormatsContentType](./kibana-plugin-plugins-data-public.fieldformatscontenttype.md) | \* | | [FieldFormatsGetConfigFn](./kibana-plugin-plugins-data-public.fieldformatsgetconfigfn.md) | | @@ -161,6 +165,7 @@ | [InputTimeRange](./kibana-plugin-plugins-data-public.inputtimerange.md) | | | [ISearchGeneric](./kibana-plugin-plugins-data-public.isearchgeneric.md) | | | [ISearchSource](./kibana-plugin-plugins-data-public.isearchsource.md) | search source interface | +| [KibanaContext](./kibana-plugin-plugins-data-public.kibanacontext.md) | | | [MatchAllFilter](./kibana-plugin-plugins-data-public.matchallfilter.md) | | | [ParsedInterval](./kibana-plugin-plugins-data-public.parsedinterval.md) | | | [PhraseFilter](./kibana-plugin-plugins-data-public.phrasefilter.md) | | diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchbar.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchbar.md index d1d20291a6799..bb45222d096a0 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchbar.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchbar.md @@ -7,7 +7,7 @@ Signature: ```typescript -SearchBar: React.ComponentClass, "query" | "isLoading" | "filters" | "onRefresh" | "onRefreshChange" | "refreshInterval" | "indexPatterns" | "dataTestSubj" | "timeHistory" | "customSubmitButton" | "screenTitle" | "showQueryBar" | "showQueryInput" | "showFilterBar" | "showDatePicker" | "showAutoRefreshOnly" | "isRefreshPaused" | "dateRangeFrom" | "dateRangeTo" | "showSaveQuery" | "savedQuery" | "onQueryChange" | "onQuerySubmit" | "onSaved" | "onSavedQueryUpdated" | "onClearSavedQuery" | "indicateNoData" | "onFiltersUpdated">, any> & { - WrappedComponent: React.ComponentType & ReactIntl.InjectedIntlProps>; +SearchBar: React.ComponentClass, "query" | "isLoading" | "filters" | "onRefresh" | "onRefreshChange" | "refreshInterval" | "indexPatterns" | "dataTestSubj" | "screenTitle" | "showQueryInput" | "showDatePicker" | "showAutoRefreshOnly" | "dateRangeFrom" | "dateRangeTo" | "isRefreshPaused" | "customSubmitButton" | "timeHistory" | "indicateNoData" | "onFiltersUpdated" | "savedQuery" | "showSaveQuery" | "onClearSavedQuery" | "showQueryBar" | "showFilterBar" | "onQueryChange" | "onQuerySubmit" | "onSaved" | "onSavedQueryUpdated">, any> & { + WrappedComponent: React.ComponentType & ReactIntl.InjectedIntlProps>; } ``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.executioncontextsearch.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.executioncontextsearch.md new file mode 100644 index 0000000000000..2f94dbe970d44 --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.executioncontextsearch.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [ExecutionContextSearch](./kibana-plugin-plugins-data-server.executioncontextsearch.md) + +## ExecutionContextSearch type + +Signature: + +```typescript +export declare type ExecutionContextSearch = { + filters?: Filter[]; + query?: Query | Query[]; + timeRange?: TimeRange; +}; +``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.expressionfunctionkibana.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.expressionfunctionkibana.md new file mode 100644 index 0000000000000..d80ff78dd803c --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.expressionfunctionkibana.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [ExpressionFunctionKibana](./kibana-plugin-plugins-data-server.expressionfunctionkibana.md) + +## ExpressionFunctionKibana type + +Signature: + +```typescript +export declare type ExpressionFunctionKibana = ExpressionFunctionDefinition<'kibana', ExpressionValueSearchContext | null, object, ExpressionValueSearchContext, ExecutionContext>; +``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.expressionfunctionkibanacontext.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.expressionfunctionkibanacontext.md new file mode 100644 index 0000000000000..b67f7b8c4b60d --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.expressionfunctionkibanacontext.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [ExpressionFunctionKibanaContext](./kibana-plugin-plugins-data-server.expressionfunctionkibanacontext.md) + +## ExpressionFunctionKibanaContext type + +Signature: + +```typescript +export declare type ExpressionFunctionKibanaContext = ExpressionFunctionDefinition<'kibana_context', KibanaContext | null, Arguments, Promise, ExecutionContext>; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionvaluesearchcontext.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.expressionvaluesearchcontext.md similarity index 54% rename from docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionvaluesearchcontext.md rename to docs/development/plugins/data/server/kibana-plugin-plugins-data-server.expressionvaluesearchcontext.md index bf64dfe4c86f7..8015482ddec1e 100644 --- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionvaluesearchcontext.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.expressionvaluesearchcontext.md @@ -1,6 +1,6 @@ -[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionValueSearchContext](./kibana-plugin-plugins-expressions-public.expressionvaluesearchcontext.md) +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [ExpressionValueSearchContext](./kibana-plugin-plugins-data-server.expressionvaluesearchcontext.md) ## ExpressionValueSearchContext type diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.getcapabilitiesforrollupindices.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.getcapabilitiesforrollupindices.md new file mode 100644 index 0000000000000..ba2efcc9b75ca --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.getcapabilitiesforrollupindices.md @@ -0,0 +1,28 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [getCapabilitiesForRollupIndices](./kibana-plugin-plugins-data-server.getcapabilitiesforrollupindices.md) + +## getCapabilitiesForRollupIndices() function + +Signature: + +```typescript +export declare function getCapabilitiesForRollupIndices(indices: { + [key: string]: any; +}): { + [key: string]: any; +}; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| indices | {
[key: string]: any;
} | | + +Returns: + +`{ + [key: string]: any; +}` + diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternsfetcher.getfieldsforwildcard.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternsfetcher.getfieldsforwildcard.md index addd29916d81d..f0989097a727d 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternsfetcher.getfieldsforwildcard.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternsfetcher.getfieldsforwildcard.md @@ -15,6 +15,8 @@ getFieldsForWildcard(options: { fieldCapsOptions?: { allow_no_indices: boolean; }; + type?: string; + rollupIndex?: string; }): Promise; ``` @@ -22,7 +24,7 @@ getFieldsForWildcard(options: { | Parameter | Type | Description | | --- | --- | --- | -| options | {
pattern: string | string[];
metaFields?: string[];
fieldCapsOptions?: {
allow_no_indices: boolean;
};
} | | +| options | {
pattern: string | string[];
metaFields?: string[];
fieldCapsOptions?: {
allow_no_indices: boolean;
};
type?: string;
rollupIndex?: string;
} | | Returns: diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternsservice.start.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternsservice.start.md index e7c331bad64e8..6528b1c213cca 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternsservice.start.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternsservice.start.md @@ -8,7 +8,7 @@ ```typescript start(core: CoreStart, { fieldFormats, logger }: IndexPatternsServiceStartDeps): { - indexPatternsServiceFactory: (savedObjectsClient: SavedObjectsClientContract) => Promise; + indexPatternsServiceFactory: (savedObjectsClient: SavedObjectsClientContract, elasticsearchClient: ElasticsearchClient) => Promise; }; ``` @@ -22,6 +22,6 @@ start(core: CoreStart, { fieldFormats, logger }: IndexPatternsServiceStartDeps): Returns: `{ - indexPatternsServiceFactory: (savedObjectsClient: SavedObjectsClientContract) => Promise; + indexPatternsServiceFactory: (savedObjectsClient: SavedObjectsClientContract, elasticsearchClient: ElasticsearchClient) => Promise; }` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanacontext.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.kibanacontext.md similarity index 51% rename from docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanacontext.md rename to docs/development/plugins/data/server/kibana-plugin-plugins-data-server.kibanacontext.md index 023748173e7dd..1ddc43c633b26 100644 --- a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanacontext.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.kibanacontext.md @@ -1,6 +1,6 @@ -[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [KibanaContext](./kibana-plugin-plugins-expressions-server.kibanacontext.md) +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [KibanaContext](./kibana-plugin-plugins-data-server.kibanacontext.md) ## KibanaContext type diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md index 82d0a5a3182b9..8957f6d0f06b4 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md @@ -28,6 +28,7 @@ | Function | Description | | --- | --- | +| [getCapabilitiesForRollupIndices(indices)](./kibana-plugin-plugins-data-server.getcapabilitiesforrollupindices.md) | | | [getDefaultSearchParams(uiSettingsClient)](./kibana-plugin-plugins-data-server.getdefaultsearchparams.md) | | | [getShardTimeout(config)](./kibana-plugin-plugins-data-server.getshardtimeout.md) | | | [getTime(indexPattern, timeRange, options)](./kibana-plugin-plugins-data-server.gettime.md) | | @@ -77,6 +78,7 @@ | [esQuery](./kibana-plugin-plugins-data-server.esquery.md) | | | [fieldFormats](./kibana-plugin-plugins-data-server.fieldformats.md) | | | [indexPatterns](./kibana-plugin-plugins-data-server.indexpatterns.md) | | +| [mergeCapabilitiesWithFields](./kibana-plugin-plugins-data-server.mergecapabilitieswithfields.md) | | | [search](./kibana-plugin-plugins-data-server.search.md) | | | [UI\_SETTINGS](./kibana-plugin-plugins-data-server.ui_settings.md) | | @@ -88,6 +90,10 @@ | [AggGroupName](./kibana-plugin-plugins-data-server.agggroupname.md) | | | [AggParam](./kibana-plugin-plugins-data-server.aggparam.md) | | | [EsaggsExpressionFunctionDefinition](./kibana-plugin-plugins-data-server.esaggsexpressionfunctiondefinition.md) | | +| [ExecutionContextSearch](./kibana-plugin-plugins-data-server.executioncontextsearch.md) | | +| [ExpressionFunctionKibana](./kibana-plugin-plugins-data-server.expressionfunctionkibana.md) | | +| [ExpressionFunctionKibanaContext](./kibana-plugin-plugins-data-server.expressionfunctionkibanacontext.md) | | +| [ExpressionValueSearchContext](./kibana-plugin-plugins-data-server.expressionvaluesearchcontext.md) | | | [FieldFormatsGetConfigFn](./kibana-plugin-plugins-data-server.fieldformatsgetconfigfn.md) | | | [Filter](./kibana-plugin-plugins-data-server.filter.md) | | | [IAggConfig](./kibana-plugin-plugins-data-server.iaggconfig.md) | AggConfig This class represents an aggregation, which is displayed in the left-hand nav of the Visualize app. | @@ -96,6 +102,7 @@ | [IFieldFormatsRegistry](./kibana-plugin-plugins-data-server.ifieldformatsregistry.md) | | | [IFieldParamType](./kibana-plugin-plugins-data-server.ifieldparamtype.md) | | | [IMetricAggType](./kibana-plugin-plugins-data-server.imetricaggtype.md) | | +| [KibanaContext](./kibana-plugin-plugins-data-server.kibanacontext.md) | | | [ParsedInterval](./kibana-plugin-plugins-data-server.parsedinterval.md) | | | [Query](./kibana-plugin-plugins-data-server.query.md) | | | [TabbedAggRow](./kibana-plugin-plugins-data-server.tabbedaggrow.md) | \* | diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.mergecapabilitieswithfields.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.mergecapabilitieswithfields.md new file mode 100644 index 0000000000000..2880e2d0d8f2c --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.mergecapabilitieswithfields.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [mergeCapabilitiesWithFields](./kibana-plugin-plugins-data-server.mergecapabilitieswithfields.md) + +## mergeCapabilitiesWithFields variable + +Signature: + +```typescript +mergeCapabilitiesWithFields: (rollupIndexCapabilities: { + [key: string]: any; +}, fieldsFromFieldCapsApi: { + [key: string]: any; +}, previousFields?: FieldDescriptor[]) => FieldDescriptor[] +``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.plugin.setup.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.plugin.setup.md index 139c5794f0146..43129891c5412 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.plugin.setup.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.plugin.setup.md @@ -11,7 +11,7 @@ setup(core: CoreSetup, { expressio __enhance: (enhancements: DataEnhancements) => void; search: ISearchSetup; fieldFormats: { - register: (customFieldFormat: import("../public").FieldFormatInstanceType) => number; + register: (customFieldFormat: import("../common").FieldFormatInstanceType) => number; }; }; ``` @@ -29,7 +29,7 @@ setup(core: CoreSetup, { expressio __enhance: (enhancements: DataEnhancements) => void; search: ISearchSetup; fieldFormats: { - register: (customFieldFormat: import("../public").FieldFormatInstanceType) => number; + register: (customFieldFormat: import("../common").FieldFormatInstanceType) => number; }; }` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.plugin.start.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.plugin.start.md index 03d3485fce9ee..8a3dbe5a6350c 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.plugin.start.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.plugin.start.md @@ -12,7 +12,7 @@ start(core: CoreStart): { fieldFormatServiceFactory: (uiSettings: import("src/core/server").IUiSettingsClient) => Promise; }; indexPatterns: { - indexPatternsServiceFactory: (savedObjectsClient: Pick) => Promise; + indexPatternsServiceFactory: (savedObjectsClient: Pick, elasticsearchClient: import("src/core/server").ElasticsearchClient) => Promise; }; search: ISearchStart>; }; @@ -31,7 +31,7 @@ start(core: CoreStart): { fieldFormatServiceFactory: (uiSettings: import("src/core/server").IUiSettingsClient) => Promise; }; indexPatterns: { - indexPatternsServiceFactory: (savedObjectsClient: Pick) => Promise; + indexPatternsServiceFactory: (savedObjectsClient: Pick, elasticsearchClient: import("src/core/server").ElasticsearchClient) => Promise; }; search: ISearchStart>; }` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.md index 2a1a78b8fcb1a..86d24534f7a44 100644 --- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.md +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.md @@ -9,7 +9,7 @@ Signature: ```typescript -export interface ExecutionContext +export interface ExecutionContext ``` ## Properties diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.kibana.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.kibana.md deleted file mode 100644 index abe8e0ae161ad..0000000000000 --- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.kibana.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionFunctionDefinitions](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.md) > [kibana](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.kibana.md) - -## ExpressionFunctionDefinitions.kibana property - -Signature: - -```typescript -kibana: ExpressionFunctionKibana; -``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.kibana_context.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.kibana_context.md deleted file mode 100644 index 4b58fd84e160d..0000000000000 --- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.kibana_context.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionFunctionDefinitions](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.md) > [kibana\_context](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.kibana_context.md) - -## ExpressionFunctionDefinitions.kibana\_context property - -Signature: - -```typescript -kibana_context: ExpressionFunctionKibanaContext; -``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.md index 53f090ea30c3f..c6e00842a31e6 100644 --- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.md +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.md @@ -20,8 +20,6 @@ export interface ExpressionFunctionDefinitions | [cumulative\_sum](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.cumulative_sum.md) | ExpressionFunctionCumulativeSum | | | [derivative](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.derivative.md) | ExpressionFunctionDerivative | | | [font](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.font.md) | ExpressionFunctionFont | | -| [kibana\_context](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.kibana_context.md) | ExpressionFunctionKibanaContext | | -| [kibana](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.kibana.md) | ExpressionFunctionKibana | | | [moving\_average](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.moving_average.md) | ExpressionFunctionMovingAverage | | | [theme](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.theme.md) | ExpressionFunctionTheme | | | [var\_set](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.var_set.md) | ExpressionFunctionVarSet | | diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctionkibana.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctionkibana.md deleted file mode 100644 index 8ccf48ba28527..0000000000000 --- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctionkibana.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionFunctionKibana](./kibana-plugin-plugins-expressions-public.expressionfunctionkibana.md) - -## ExpressionFunctionKibana type - -Signature: - -```typescript -export declare type ExpressionFunctionKibana = ExpressionFunctionDefinition<'kibana', ExpressionValueSearchContext | null, object, ExpressionValueSearchContext>; -``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.md index e2ad6215e25d0..2dfc67d2af5fa 100644 --- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.md +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.md @@ -21,7 +21,7 @@ export interface IExpressionLoaderParams | [disableCaching](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.disablecaching.md) | boolean | | | [inspectorAdapters](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.inspectoradapters.md) | Adapters | | | [onRenderError](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.onrendererror.md) | RenderErrorHandlerFnType | | -| [searchContext](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.searchcontext.md) | ExecutionContextSearch | | +| [searchContext](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.searchcontext.md) | SerializableState | | | [searchSessionId](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.searchsessionid.md) | string | | | [uiState](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.uistate.md) | unknown | | | [variables](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.variables.md) | Record<string, any> | | diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.searchcontext.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.searchcontext.md index 523d0c562f7ca..6b5fad950c4e9 100644 --- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.searchcontext.md +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.searchcontext.md @@ -7,5 +7,5 @@ Signature: ```typescript -searchContext?: ExecutionContextSearch; +searchContext?: SerializableState; ``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibana_context_name.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibana_context_name.md deleted file mode 100644 index e568db84f383d..0000000000000 --- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibana_context_name.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [KIBANA\_CONTEXT\_NAME](./kibana-plugin-plugins-expressions-public.kibana_context_name.md) - -## KIBANA\_CONTEXT\_NAME type - -Signature: - -```typescript -export declare type KIBANA_CONTEXT_NAME = 'kibana_context'; -``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.md index db09f966e2fa5..a03ea32482011 100644 --- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.md +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.md @@ -99,7 +99,6 @@ | [ExpressionAstExpression](./kibana-plugin-plugins-expressions-public.expressionastexpression.md) | | | [ExpressionAstFunction](./kibana-plugin-plugins-expressions-public.expressionastfunction.md) | | | [ExpressionAstNode](./kibana-plugin-plugins-expressions-public.expressionastnode.md) | | -| [ExpressionFunctionKibana](./kibana-plugin-plugins-expressions-public.expressionfunctionkibana.md) | | | [ExpressionRendererComponent](./kibana-plugin-plugins-expressions-public.expressionrenderercomponent.md) | | | [ExpressionsServiceSetup](./kibana-plugin-plugins-expressions-public.expressionsservicesetup.md) | The public contract that ExpressionsService provides to other plugins in Kibana Platform in \*setup\* life-cycle. | | [ExpressionsSetup](./kibana-plugin-plugins-expressions-public.expressionssetup.md) | Expressions public setup contract, extends [ExpressionsServiceSetup](./kibana-plugin-plugins-expressions-public.expressionsservicesetup.md) | @@ -110,13 +109,10 @@ | [ExpressionValueFilter](./kibana-plugin-plugins-expressions-public.expressionvaluefilter.md) | Represents an object that is a Filter. | | [ExpressionValueNum](./kibana-plugin-plugins-expressions-public.expressionvaluenum.md) | | | [ExpressionValueRender](./kibana-plugin-plugins-expressions-public.expressionvaluerender.md) | Represents an object that is intended to be rendered. | -| [ExpressionValueSearchContext](./kibana-plugin-plugins-expressions-public.expressionvaluesearchcontext.md) | | | [ExpressionValueUnboxed](./kibana-plugin-plugins-expressions-public.expressionvalueunboxed.md) | | | [FontLabel](./kibana-plugin-plugins-expressions-public.fontlabel.md) | This type contains a unions of all supported font labels, or the the name of the font the user would see in a UI. | | [FontValue](./kibana-plugin-plugins-expressions-public.fontvalue.md) | This type contains a union of all supported font values, equivalent to the CSS font-value property. | | [InterpreterErrorType](./kibana-plugin-plugins-expressions-public.interpretererrortype.md) | | -| [KIBANA\_CONTEXT\_NAME](./kibana-plugin-plugins-expressions-public.kibana_context_name.md) | | -| [KibanaContext](./kibana-plugin-plugins-expressions-public.kibanacontext.md) | | | [KnownTypeToString](./kibana-plugin-plugins-expressions-public.knowntypetostring.md) | Map the type of the generic to a string-based representation of the type.If the provided generic is its own type interface, we use the value of the type key as a string literal type for it. | | [PointSeries](./kibana-plugin-plugins-expressions-public.pointseries.md) | A PointSeries is a unique structure that represents dots on a chart. | | [PointSeriesColumnName](./kibana-plugin-plugins-expressions-public.pointseriescolumnname.md) | Allowed column names in a PointSeries | diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.md index 047879fd99255..e2547cc9470d1 100644 --- a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.md +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.md @@ -9,7 +9,7 @@ Signature: ```typescript -export interface ExecutionContext +export interface ExecutionContext ``` ## Properties diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.kibana.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.kibana.md deleted file mode 100644 index 8e6d189f8f450..0000000000000 --- a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.kibana.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionFunctionDefinitions](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.md) > [kibana](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.kibana.md) - -## ExpressionFunctionDefinitions.kibana property - -Signature: - -```typescript -kibana: ExpressionFunctionKibana; -``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.kibana_context.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.kibana_context.md deleted file mode 100644 index f9e248ad6d913..0000000000000 --- a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.kibana_context.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionFunctionDefinitions](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.md) > [kibana\_context](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.kibana_context.md) - -## ExpressionFunctionDefinitions.kibana\_context property - -Signature: - -```typescript -kibana_context: ExpressionFunctionKibanaContext; -``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.md index 6f152bb10b37e..219678244951b 100644 --- a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.md +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.md @@ -20,8 +20,6 @@ export interface ExpressionFunctionDefinitions | [cumulative\_sum](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.cumulative_sum.md) | ExpressionFunctionCumulativeSum | | | [derivative](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.derivative.md) | ExpressionFunctionDerivative | | | [font](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.font.md) | ExpressionFunctionFont | | -| [kibana\_context](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.kibana_context.md) | ExpressionFunctionKibanaContext | | -| [kibana](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.kibana.md) | ExpressionFunctionKibana | | | [moving\_average](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.moving_average.md) | ExpressionFunctionMovingAverage | | | [theme](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.theme.md) | ExpressionFunctionTheme | | | [var\_set](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.var_set.md) | ExpressionFunctionVarSet | | diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctionkibana.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctionkibana.md deleted file mode 100644 index aac2ae1c3ca4e..0000000000000 --- a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctionkibana.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionFunctionKibana](./kibana-plugin-plugins-expressions-server.expressionfunctionkibana.md) - -## ExpressionFunctionKibana type - -Signature: - -```typescript -export declare type ExpressionFunctionKibana = ExpressionFunctionDefinition<'kibana', ExpressionValueSearchContext | null, object, ExpressionValueSearchContext>; -``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibana_context_name.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibana_context_name.md deleted file mode 100644 index bd47c52e0d5ce..0000000000000 --- a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibana_context_name.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [KIBANA\_CONTEXT\_NAME](./kibana-plugin-plugins-expressions-server.kibana_context_name.md) - -## KIBANA\_CONTEXT\_NAME type - -Signature: - -```typescript -export declare type KIBANA_CONTEXT_NAME = 'kibana_context'; -``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.md index 9e2189dad2732..5f7f373cd927f 100644 --- a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.md +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.md @@ -83,7 +83,6 @@ | [ExpressionAstExpression](./kibana-plugin-plugins-expressions-server.expressionastexpression.md) | | | [ExpressionAstFunction](./kibana-plugin-plugins-expressions-server.expressionastfunction.md) | | | [ExpressionAstNode](./kibana-plugin-plugins-expressions-server.expressionastnode.md) | | -| [ExpressionFunctionKibana](./kibana-plugin-plugins-expressions-server.expressionfunctionkibana.md) | | | [ExpressionsServerSetup](./kibana-plugin-plugins-expressions-server.expressionsserversetup.md) | | | [ExpressionsServerStart](./kibana-plugin-plugins-expressions-server.expressionsserverstart.md) | | | [ExpressionValue](./kibana-plugin-plugins-expressions-server.expressionvalue.md) | | @@ -93,13 +92,10 @@ | [ExpressionValueFilter](./kibana-plugin-plugins-expressions-server.expressionvaluefilter.md) | Represents an object that is a Filter. | | [ExpressionValueNum](./kibana-plugin-plugins-expressions-server.expressionvaluenum.md) | | | [ExpressionValueRender](./kibana-plugin-plugins-expressions-server.expressionvaluerender.md) | Represents an object that is intended to be rendered. | -| [ExpressionValueSearchContext](./kibana-plugin-plugins-expressions-server.expressionvaluesearchcontext.md) | | | [ExpressionValueUnboxed](./kibana-plugin-plugins-expressions-server.expressionvalueunboxed.md) | | | [FontLabel](./kibana-plugin-plugins-expressions-server.fontlabel.md) | This type contains a unions of all supported font labels, or the the name of the font the user would see in a UI. | | [FontValue](./kibana-plugin-plugins-expressions-server.fontvalue.md) | This type contains a union of all supported font values, equivalent to the CSS font-value property. | | [InterpreterErrorType](./kibana-plugin-plugins-expressions-server.interpretererrortype.md) | | -| [KIBANA\_CONTEXT\_NAME](./kibana-plugin-plugins-expressions-server.kibana_context_name.md) | | -| [KibanaContext](./kibana-plugin-plugins-expressions-server.kibanacontext.md) | | | [KnownTypeToString](./kibana-plugin-plugins-expressions-server.knowntypetostring.md) | Map the type of the generic to a string-based representation of the type.If the provided generic is its own type interface, we use the value of the type key as a string literal type for it. | | [PointSeries](./kibana-plugin-plugins-expressions-server.pointseries.md) | A PointSeries is a unique structure that represents dots on a chart. | | [PointSeriesColumnName](./kibana-plugin-plugins-expressions-server.pointseriescolumnname.md) | Allowed column names in a PointSeries | diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.addtriggeraction.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.addtriggeraction.md index ba9060e01e57d..5a1ab83551d34 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.addtriggeraction.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.addtriggeraction.md @@ -11,5 +11,5 @@ Signature: ```typescript -readonly addTriggerAction: (triggerId: T, action: ActionDefinition | Action) => void; +readonly addTriggerAction: (triggerId: T, action: ActionDefinition | Action) => void; ``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.getaction.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.getaction.md index 3e433809f9471..5b0b3eea01cb1 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.getaction.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.getaction.md @@ -7,5 +7,5 @@ Signature: ```typescript -readonly getAction: >(id: string) => Action, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK">; +readonly getAction: >(id: string) => Action, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION">; ``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggeractions.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggeractions.md index 83afcab29689d..2dda422046318 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggeractions.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggeractions.md @@ -7,5 +7,5 @@ Signature: ```typescript -readonly getTriggerActions: (triggerId: T) => Action[]; +readonly getTriggerActions: (triggerId: T) => Action[]; ``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggercompatibleactions.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggercompatibleactions.md index 879f5a3d8628a..e087753726a8a 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggercompatibleactions.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggercompatibleactions.md @@ -7,5 +7,5 @@ Signature: ```typescript -readonly getTriggerCompatibleActions: (triggerId: T, context: TriggerContextMapping[T]) => Promise[]>; +readonly getTriggerCompatibleActions: (triggerId: T, context: TriggerContextMapping[T]) => Promise[]>; ``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.md index 7fade7c4c841b..f9eb693b492f7 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.md @@ -21,19 +21,19 @@ export declare class UiActionsService | Property | Modifiers | Type | Description | | --- | --- | --- | --- | | [actions](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.actions.md) | | ActionRegistry | | -| [addTriggerAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.addtriggeraction.md) | | <T extends "" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER" | "FILTER_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER">(triggerId: T, action: ActionDefinition<TriggerContextMapping[T]> | Action<TriggerContextMapping[T], "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK">) => void | addTriggerAction is similar to attachAction as it attaches action to a trigger, but it also registers the action, if it has not been registered, yet.addTriggerAction also infers better typing of the action argument. | +| [addTriggerAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.addtriggeraction.md) | | <T extends "" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER" | "FILTER_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER">(triggerId: T, action: ActionDefinition<TriggerContextMapping[T]> | Action<TriggerContextMapping[T], "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION">) => void | addTriggerAction is similar to attachAction as it attaches action to a trigger, but it also registers the action, if it has not been registered, yet.addTriggerAction also infers better typing of the action argument. | | [attachAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.attachaction.md) | | <T extends "" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER" | "FILTER_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER">(triggerId: T, actionId: string) => void | | | [clear](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.clear.md) | | () => void | Removes all registered triggers and actions. | | [detachAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.detachaction.md) | | (triggerId: TriggerId, actionId: string) => void | | | [executeTriggerActions](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.executetriggeractions.md) | | <T extends "" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER" | "FILTER_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER">(triggerId: T, context: TriggerContext<T>) => Promise<void> | | | [executionService](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.executionservice.md) | | UiActionsExecutionService | | | [fork](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.fork.md) | | () => UiActionsService | "Fork" a separate instance of UiActionsService that inherits all existing triggers and actions, but going forward all new triggers and actions added to this instance of UiActionsService are only available within this instance. | -| [getAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.getaction.md) | | <T extends ActionDefinition<{}>>(id: string) => Action<ActionContext<T>, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK"> | | +| [getAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.getaction.md) | | <T extends ActionDefinition<{}>>(id: string) => Action<ActionContext<T>, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION"> | | | [getTrigger](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettrigger.md) | | <T extends "" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER" | "FILTER_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER">(triggerId: T) => TriggerContract<T> | | -| [getTriggerActions](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggeractions.md) | | <T extends "" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER" | "FILTER_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER">(triggerId: T) => Action<TriggerContextMapping[T], "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK">[] | | -| [getTriggerCompatibleActions](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggercompatibleactions.md) | | <T extends "" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER" | "FILTER_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER">(triggerId: T, context: TriggerContextMapping[T]) => Promise<Action<TriggerContextMapping[T], "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK">[]> | | +| [getTriggerActions](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggeractions.md) | | <T extends "" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER" | "FILTER_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER">(triggerId: T) => Action<TriggerContextMapping[T], "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION">[] | | +| [getTriggerCompatibleActions](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggercompatibleactions.md) | | <T extends "" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER" | "FILTER_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER">(triggerId: T, context: TriggerContextMapping[T]) => Promise<Action<TriggerContextMapping[T], "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION">[]> | | | [hasAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.hasaction.md) | | (actionId: string) => boolean | | -| [registerAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.registeraction.md) | | <A extends ActionDefinition<{}>>(definition: A) => Action<ActionContext<A>, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK"> | | +| [registerAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.registeraction.md) | | <A extends ActionDefinition<{}>>(definition: A) => Action<ActionContext<A>, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION"> | | | [registerTrigger](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.registertrigger.md) | | (trigger: Trigger) => void | | | [triggers](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.triggers.md) | | TriggerRegistry | | | [triggerToActions](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.triggertoactions.md) | | TriggerToActionsRegistry | | diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.registeraction.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.registeraction.md index eeda7b503037d..bd340eb76fbac 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.registeraction.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.registeraction.md @@ -7,5 +7,5 @@ Signature: ```typescript -readonly registerAction: >(definition: A) => Action, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK">; +readonly registerAction: >(definition: A) => Action, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION">; ``` diff --git a/package.json b/package.json index ade567c840da7..353d3dc85356c 100644 --- a/package.json +++ b/package.json @@ -345,8 +345,8 @@ "@babel/register": "^7.10.5", "@babel/traverse": "^7.11.5", "@babel/types": "^7.11.0", - "@cypress/snapshot": "^2.1.3", - "@cypress/webpack-preprocessor": "^5.4.1", + "@cypress/snapshot": "^2.1.7", + "@cypress/webpack-preprocessor": "^5.4.10", "@elastic/apm-rum": "^5.6.1", "@elastic/apm-rum-react": "^1.2.5", "@elastic/charts": "24.0.0", @@ -609,9 +609,9 @@ "cpy": "^8.1.1", "cronstrue": "^1.51.0", "css-loader": "^3.4.2", - "cypress": "^5.4.0", + "cypress": "^5.5.0", "cypress-cucumber-preprocessor": "^2.5.2", - "cypress-multi-reporters": "^1.2.3", + "cypress-multi-reporters": "^1.4.0", "d3": "3.5.17", "d3-cloud": "1.2.5", "d3-scale": "1.0.7", @@ -633,7 +633,7 @@ "eslint-module-utils": "2.5.0", "eslint-plugin-babel": "^5.3.0", "eslint-plugin-ban": "^1.4.0", - "eslint-plugin-cypress": "^2.8.1", + "eslint-plugin-cypress": "^2.11.2", "eslint-plugin-eslint-comments": "^3.2.0", "eslint-plugin-import": "^2.19.1", "eslint-plugin-jest": "^24.0.2", @@ -663,10 +663,9 @@ "graphql-codegen-typescript-common": "^0.18.2", "graphql-codegen-typescript-resolvers": "^0.18.2", "graphql-codegen-typescript-server": "^0.18.2", - "grunt": "1.0.4", + "grunt": "1.3.0", "grunt-available-tasks": "^0.6.3", "grunt-babel": "^8.0.0", - "grunt-cli": "^1.2.0", "grunt-contrib-clean": "^1.1.0", "grunt-contrib-copy": "^1.0.0", "grunt-contrib-watch": "^1.1.0", diff --git a/src/core/server/saved_objects/service/lib/search_dsl/query_params.test.ts b/src/core/server/saved_objects/service/lib/search_dsl/query_params.test.ts index 333f5caf72525..c35ec809fcf8d 100644 --- a/src/core/server/saved_objects/service/lib/search_dsl/query_params.test.ts +++ b/src/core/server/saved_objects/service/lib/search_dsl/query_params.test.ts @@ -21,28 +21,64 @@ import { esKuery } from '../../../es_query'; type KueryNode = any; -import { typeRegistryMock } from '../../../saved_objects_type_registry.mock'; -import { ALL_NAMESPACES_STRING } from '../utils'; +import { ALL_NAMESPACES_STRING, DEFAULT_NAMESPACE_STRING } from '../utils'; +import { SavedObjectTypeRegistry } from '../../../saved_objects_type_registry'; import { getQueryParams, getClauseForReference } from './query_params'; -const registry = typeRegistryMock.create(); +const registerTypes = (registry: SavedObjectTypeRegistry) => { + registry.registerType({ + name: 'pending', + hidden: false, + namespaceType: 'single', + mappings: { + properties: { title: { type: 'text' } }, + }, + management: { + defaultSearchField: 'title', + }, + }); -const MAPPINGS = { - properties: { - pending: { properties: { title: { type: 'text' } } }, - saved: { + registry.registerType({ + name: 'saved', + hidden: false, + namespaceType: 'single', + mappings: { properties: { title: { type: 'text', fields: { raw: { type: 'keyword' } } }, obj: { properties: { key1: { type: 'text' } } }, }, }, - // mock registry returns isMultiNamespace=true for 'shared' type - shared: { properties: { name: { type: 'keyword' } } }, - // mock registry returns isNamespaceAgnostic=true for 'global' type - global: { properties: { name: { type: 'keyword' } } }, - }, + management: { + defaultSearchField: 'title', + }, + }); + + registry.registerType({ + name: 'shared', + hidden: false, + namespaceType: 'multiple', + mappings: { + properties: { name: { type: 'keyword' } }, + }, + management: { + defaultSearchField: 'name', + }, + }); + + registry.registerType({ + name: 'global', + hidden: false, + namespaceType: 'agnostic', + mappings: { + properties: { name: { type: 'keyword' } }, + }, + management: { + defaultSearchField: 'name', + }, + }); }; -const ALL_TYPES = Object.keys(MAPPINGS.properties); + +const ALL_TYPES = ['pending', 'saved', 'shared', 'global']; // get all possible subsets (combination) of all types const ALL_TYPE_SUBSETS = ALL_TYPES.reduce( (subsets, value) => subsets.concat(subsets.map((set) => [...set, value])), @@ -51,48 +87,58 @@ const ALL_TYPE_SUBSETS = ALL_TYPES.reduce( .filter((x) => x.length) // exclude empty set .map((x) => (x.length === 1 ? x[0] : x)); // if a subset is a single string, destructure it -const createTypeClause = (type: string, namespaces?: string[]) => { - if (registry.isMultiNamespace(type)) { - const array = [...(namespaces ?? ['default']), ALL_NAMESPACES_STRING]; - return { - bool: { - must: expect.arrayContaining([{ terms: { namespaces: array } }]), - must_not: [{ exists: { field: 'namespace' } }], - }, - }; - } else if (registry.isSingleNamespace(type)) { - const nonDefaultNamespaces = namespaces?.filter((n) => n !== 'default') ?? []; - const should: any = []; - if (nonDefaultNamespaces.length > 0) { - should.push({ terms: { namespace: nonDefaultNamespaces } }); - } - if (namespaces?.includes('default')) { - should.push({ bool: { must_not: [{ exists: { field: 'namespace' } }] } }); - } - return { - bool: { - must: [{ term: { type } }], - should: expect.arrayContaining(should), - minimum_should_match: 1, - must_not: [{ exists: { field: 'namespaces' } }], - }, - }; - } - // isNamespaceAgnostic - return { - bool: expect.objectContaining({ - must_not: [{ exists: { field: 'namespace' } }, { exists: { field: 'namespaces' } }], - }), - }; -}; - /** * Note: these tests cases are defined in the order they appear in the source code, for readability's sake */ describe('#getQueryParams', () => { - const mappings = MAPPINGS; + let registry: SavedObjectTypeRegistry; type Result = ReturnType; + beforeEach(() => { + registry = new SavedObjectTypeRegistry(); + registerTypes(registry); + }); + + const createTypeClause = (type: string, namespaces?: string[]) => { + if (registry.isMultiNamespace(type)) { + const array = [...(namespaces ?? [DEFAULT_NAMESPACE_STRING]), ALL_NAMESPACES_STRING]; + + const namespacesClause = { terms: { namespaces: array } }; + return { + bool: { + must: namespaces?.includes(ALL_NAMESPACES_STRING) + ? expect.not.arrayContaining([namespacesClause]) + : expect.arrayContaining([namespacesClause]), + must_not: [{ exists: { field: 'namespace' } }], + }, + }; + } else if (registry.isSingleNamespace(type)) { + const nonDefaultNamespaces = namespaces?.filter((n) => n !== DEFAULT_NAMESPACE_STRING) ?? []; + const searchingAcrossAllNamespaces = namespaces?.includes(ALL_NAMESPACES_STRING) ?? false; + const should: any = []; + if (nonDefaultNamespaces.length > 0 && !searchingAcrossAllNamespaces) { + should.push({ terms: { namespace: nonDefaultNamespaces } }); + } + if (namespaces?.includes(DEFAULT_NAMESPACE_STRING)) { + should.push({ bool: { must_not: [{ exists: { field: 'namespace' } }] } }); + } + return { + bool: { + must: [{ term: { type } }], + should: expect.arrayContaining(should), + minimum_should_match: 1, + must_not: [{ exists: { field: 'namespaces' } }], + }, + }; + } + // isNamespaceAgnostic + return { + bool: expect.objectContaining({ + must_not: [{ exists: { field: 'namespace' } }, { exists: { field: 'namespaces' } }], + }), + }; + }; + describe('kueryNode filter clause', () => { const expectResult = (result: Result, expected: any) => { expect(result.query.bool.filter).toEqual(expect.arrayContaining([expected])); @@ -100,13 +146,13 @@ describe('#getQueryParams', () => { describe('`kueryNode` parameter', () => { it('does not include the clause when `kueryNode` is not specified', () => { - const result = getQueryParams({ mappings, registry, kueryNode: undefined }); + const result = getQueryParams({ registry, kueryNode: undefined }); expect(result.query.bool.filter).toHaveLength(1); }); it('includes the specified Kuery clause', () => { const test = (kueryNode: KueryNode) => { - const result = getQueryParams({ mappings, registry, kueryNode }); + const result = getQueryParams({ registry, kueryNode }); const expected = esKuery.toElasticsearchQuery(kueryNode); expect(result.query.bool.filter).toHaveLength(2); expectResult(result, expected); @@ -165,7 +211,6 @@ describe('#getQueryParams', () => { it('does not include the clause when `hasReference` is not specified', () => { const result = getQueryParams({ - mappings, registry, hasReference: undefined, }); @@ -176,7 +221,6 @@ describe('#getQueryParams', () => { it('creates a should clause for specified reference when operator is `OR`', () => { const hasReference = { id: 'foo', type: 'bar' }; const result = getQueryParams({ - mappings, registry, hasReference, hasReferenceOperator: 'OR', @@ -192,7 +236,6 @@ describe('#getQueryParams', () => { it('creates a must clause for specified reference when operator is `AND`', () => { const hasReference = { id: 'foo', type: 'bar' }; const result = getQueryParams({ - mappings, registry, hasReference, hasReferenceOperator: 'AND', @@ -210,7 +253,6 @@ describe('#getQueryParams', () => { { id: 'hello', type: 'dolly' }, ]; const result = getQueryParams({ - mappings, registry, hasReference, hasReferenceOperator: 'OR', @@ -229,7 +271,6 @@ describe('#getQueryParams', () => { { id: 'hello', type: 'dolly' }, ]; const result = getQueryParams({ - mappings, registry, hasReference, hasReferenceOperator: 'AND', @@ -244,7 +285,6 @@ describe('#getQueryParams', () => { it('defaults to `OR` when operator is not specified', () => { const hasReference = { id: 'foo', type: 'bar' }; const result = getQueryParams({ - mappings, registry, hasReference, }); @@ -278,14 +318,13 @@ describe('#getQueryParams', () => { }; it('searches for all known types when `type` is not specified', () => { - const result = getQueryParams({ mappings, registry, type: undefined }); + const result = getQueryParams({ registry, type: undefined }); expectResult(result, ...ALL_TYPES); }); it('searches for specified type/s', () => { const test = (typeOrTypes: string | string[]) => { const result = getQueryParams({ - mappings, registry, type: typeOrTypes, }); @@ -309,18 +348,17 @@ describe('#getQueryParams', () => { const test = (namespaces?: string[]) => { for (const typeOrTypes of ALL_TYPE_SUBSETS) { - const result = getQueryParams({ mappings, registry, type: typeOrTypes, namespaces }); + const result = getQueryParams({ registry, type: typeOrTypes, namespaces }); const types = Array.isArray(typeOrTypes) ? typeOrTypes : [typeOrTypes]; expectResult(result, ...types.map((x) => createTypeClause(x, namespaces))); } // also test with no specified type/s - const result = getQueryParams({ mappings, registry, type: undefined, namespaces }); + const result = getQueryParams({ registry, type: undefined, namespaces }); expectResult(result, ...ALL_TYPES.map((x) => createTypeClause(x, namespaces))); }; - it('normalizes and deduplicates provided namespaces', () => { + it('deduplicates provided namespaces', () => { const result = getQueryParams({ - mappings, registry, search: '*', namespaces: ['foo', '*', 'foo', 'bar', 'default'], @@ -328,7 +366,7 @@ describe('#getQueryParams', () => { expectResult( result, - ...ALL_TYPES.map((x) => createTypeClause(x, ['foo', 'default', 'bar'])) + ...ALL_TYPES.map((x) => createTypeClause(x, ['foo', '*', 'bar', 'default'])) ); }); @@ -360,7 +398,6 @@ describe('#getQueryParams', () => { it('supersedes `type` and `namespaces` parameters', () => { const result = getQueryParams({ - mappings, registry, type: ['pending', 'saved', 'shared', 'global'], namespaces: ['foo', 'bar', 'default'], @@ -381,148 +418,266 @@ describe('#getQueryParams', () => { }); }); - describe('search clause (query.bool.must.simple_query_string)', () => { - const search = 'foo*'; + describe('search clause (query.bool)', () => { + describe('when using simple search (query.bool.must.simple_query_string)', () => { + const search = 'foo'; - const expectResult = (result: Result, sqsClause: any) => { - expect(result.query.bool.must).toEqual([{ simple_query_string: sqsClause }]); - }; + const expectResult = (result: Result, sqsClause: any) => { + expect(result.query.bool.must).toEqual([{ simple_query_string: sqsClause }]); + }; - describe('`search` parameter', () => { - it('does not include clause when `search` is not specified', () => { - const result = getQueryParams({ - mappings, - registry, - search: undefined, + describe('`search` parameter', () => { + it('does not include clause when `search` is not specified', () => { + const result = getQueryParams({ + registry, + search: undefined, + }); + expect(result.query.bool.must).toBeUndefined(); }); - expect(result.query.bool.must).toBeUndefined(); - }); - it('creates a clause with query for specified search', () => { - const result = getQueryParams({ - mappings, - registry, - search, + it('creates a clause with query for specified search', () => { + const result = getQueryParams({ + registry, + search, + }); + expectResult(result, expect.objectContaining({ query: search })); }); - expectResult(result, expect.objectContaining({ query: search })); }); - }); - describe('`searchFields` and `rootSearchFields` parameters', () => { - const getExpectedFields = (searchFields: string[], typeOrTypes: string | string[]) => { - const types = Array.isArray(typeOrTypes) ? typeOrTypes : [typeOrTypes]; - return searchFields.map((x) => types.map((y) => `${y}.${x}`)).flat(); - }; + describe('`searchFields` and `rootSearchFields` parameters', () => { + const getExpectedFields = (searchFields: string[], typeOrTypes: string | string[]) => { + const types = Array.isArray(typeOrTypes) ? typeOrTypes : [typeOrTypes]; + return searchFields.map((x) => types.map((y) => `${y}.${x}`)).flat(); + }; - const test = ({ - searchFields, - rootSearchFields, - }: { - searchFields?: string[]; - rootSearchFields?: string[]; - }) => { - for (const typeOrTypes of ALL_TYPE_SUBSETS) { + const test = ({ + searchFields, + rootSearchFields, + }: { + searchFields?: string[]; + rootSearchFields?: string[]; + }) => { + for (const typeOrTypes of ALL_TYPE_SUBSETS) { + const result = getQueryParams({ + registry, + type: typeOrTypes, + search, + searchFields, + rootSearchFields, + }); + let fields = rootSearchFields || []; + if (searchFields) { + fields = fields.concat(getExpectedFields(searchFields, typeOrTypes)); + } + expectResult(result, expect.objectContaining({ fields })); + } + // also test with no specified type/s const result = getQueryParams({ - mappings, registry, - type: typeOrTypes, + type: undefined, search, searchFields, rootSearchFields, }); let fields = rootSearchFields || []; if (searchFields) { - fields = fields.concat(getExpectedFields(searchFields, typeOrTypes)); + fields = fields.concat(getExpectedFields(searchFields, ALL_TYPES)); } expectResult(result, expect.objectContaining({ fields })); - } - // also test with no specified type/s - const result = getQueryParams({ - mappings, - registry, - type: undefined, - search, - searchFields, - rootSearchFields, + }; + + it('throws an error if a raw search field contains a "." character', () => { + expect(() => + getQueryParams({ + registry, + type: undefined, + search, + searchFields: undefined, + rootSearchFields: ['foo', 'bar.baz'], + }) + ).toThrowErrorMatchingInlineSnapshot( + `"rootSearchFields entry \\"bar.baz\\" is invalid: cannot contain \\".\\" character"` + ); }); - let fields = rootSearchFields || []; - if (searchFields) { - fields = fields.concat(getExpectedFields(searchFields, ALL_TYPES)); - } - expectResult(result, expect.objectContaining({ fields })); - }; - it('throws an error if a raw search field contains a "." character', () => { - expect(() => - getQueryParams({ - mappings, + it('includes lenient flag and all fields when `searchFields` and `rootSearchFields` are not specified', () => { + const result = getQueryParams({ registry, - type: undefined, search, searchFields: undefined, - rootSearchFields: ['foo', 'bar.baz'], - }) - ).toThrowErrorMatchingInlineSnapshot( - `"rootSearchFields entry \\"bar.baz\\" is invalid: cannot contain \\".\\" character"` - ); + rootSearchFields: undefined, + }); + expectResult(result, expect.objectContaining({ lenient: true, fields: ['*'] })); + }); + + it('includes specified search fields for appropriate type/s', () => { + test({ searchFields: ['title'] }); + }); + + it('supports boosting', () => { + test({ searchFields: ['title^3'] }); + }); + + it('supports multiple search fields', () => { + test({ searchFields: ['title, title.raw'] }); + }); + + it('includes specified raw search fields', () => { + test({ rootSearchFields: ['_id'] }); + }); + + it('supports multiple raw search fields', () => { + test({ rootSearchFields: ['_id', 'originId'] }); + }); + + it('supports search fields and raw search fields', () => { + test({ searchFields: ['title'], rootSearchFields: ['_id'] }); + }); }); - it('includes lenient flag and all fields when `searchFields` and `rootSearchFields` are not specified', () => { - const result = getQueryParams({ - mappings, + describe('`defaultSearchOperator` parameter', () => { + it('does not include default_operator when `defaultSearchOperator` is not specified', () => { + const result = getQueryParams({ + registry, + search, + defaultSearchOperator: undefined, + }); + expectResult( + result, + expect.not.objectContaining({ default_operator: expect.anything() }) + ); + }); + + it('includes specified default operator', () => { + const defaultSearchOperator = 'AND'; + const result = getQueryParams({ + registry, + search, + defaultSearchOperator, + }); + expectResult( + result, + expect.objectContaining({ default_operator: defaultSearchOperator }) + ); + }); + }); + }); + + describe('when using prefix search (query.bool.should)', () => { + const searchQuery = 'foo*'; + + const getQueryParamForSearch = ({ + search, + searchFields, + type, + }: { + search?: string; + searchFields?: string[]; + type?: string[]; + }) => + getQueryParams({ registry, search, - searchFields: undefined, - rootSearchFields: undefined, + searchFields, + type, }); - expectResult(result, expect.objectContaining({ lenient: true, fields: ['*'] })); - }); - it('includes specified search fields for appropriate type/s', () => { - test({ searchFields: ['title'] }); - }); + it('uses a `should` clause instead of `must`', () => { + const result = getQueryParamForSearch({ search: searchQuery, searchFields: ['title'] }); - it('supports boosting', () => { - test({ searchFields: ['title^3'] }); + expect(result.query.bool.must).toBeUndefined(); + expect(result.query.bool.should).toEqual(expect.any(Array)); + expect(result.query.bool.should.length).toBeGreaterThanOrEqual(1); + expect(result.query.bool.minimum_should_match).toBe(1); }); - - it('supports multiple search fields', () => { - test({ searchFields: ['title, title.raw'] }); + it('includes the `simple_query_string` in the `should` clauses', () => { + const result = getQueryParamForSearch({ search: searchQuery, searchFields: ['title'] }); + expect(result.query.bool.should[0]).toEqual({ + simple_query_string: expect.objectContaining({ + query: searchQuery, + }), + }); }); - it('includes specified raw search fields', () => { - test({ rootSearchFields: ['_id'] }); + it('adds a should clause for each `searchFields` / `type` tuple', () => { + const result = getQueryParamForSearch({ + search: searchQuery, + searchFields: ['title', 'desc'], + type: ['saved', 'pending'], + }); + const shouldClauses = result.query.bool.should; + + expect(shouldClauses.length).toBe(5); + + const mppClauses = shouldClauses.slice(1); + + expect( + mppClauses.map((clause: any) => Object.keys(clause.match_phrase_prefix)[0]) + ).toEqual(['saved.title', 'pending.title', 'saved.desc', 'pending.desc']); }); - it('supports multiple raw search fields', () => { - test({ rootSearchFields: ['_id', 'originId'] }); + it('uses all registered types when `type` is not provided', () => { + const result = getQueryParamForSearch({ + search: searchQuery, + searchFields: ['title'], + type: undefined, + }); + const shouldClauses = result.query.bool.should; + + expect(shouldClauses.length).toBe(5); + + const mppClauses = shouldClauses.slice(1); + + expect( + mppClauses.map((clause: any) => Object.keys(clause.match_phrase_prefix)[0]) + ).toEqual(['pending.title', 'saved.title', 'shared.title', 'global.title']); }); - it('supports search fields and raw search fields', () => { - test({ searchFields: ['title'], rootSearchFields: ['_id'] }); + it('removes the prefix search wildcard from the query', () => { + const result = getQueryParamForSearch({ + search: searchQuery, + searchFields: ['title'], + type: ['saved'], + }); + const shouldClauses = result.query.bool.should; + const mppClauses = shouldClauses.slice(1); + + expect(mppClauses[0].match_phrase_prefix['saved.title'].query).toEqual('foo'); }); - }); - describe('`defaultSearchOperator` parameter', () => { - it('does not include default_operator when `defaultSearchOperator` is not specified', () => { - const result = getQueryParams({ - mappings, - registry, - search, - defaultSearchOperator: undefined, + it("defaults to the type's default search field when `searchFields` is not specified", () => { + const result = getQueryParamForSearch({ + search: searchQuery, + searchFields: undefined, + type: ['saved', 'global'], }); - expectResult(result, expect.not.objectContaining({ default_operator: expect.anything() })); + const shouldClauses = result.query.bool.should; + + expect(shouldClauses.length).toBe(3); + + const mppClauses = shouldClauses.slice(1); + + expect( + mppClauses.map((clause: any) => Object.keys(clause.match_phrase_prefix)[0]) + ).toEqual(['saved.title', 'global.name']); }); - it('includes specified default operator', () => { - const defaultSearchOperator = 'AND'; - const result = getQueryParams({ - mappings, - registry, - search, - defaultSearchOperator, + it('supports boosting', () => { + const result = getQueryParamForSearch({ + search: searchQuery, + searchFields: ['title^3', 'description'], + type: ['saved'], }); - expectResult(result, expect.objectContaining({ default_operator: defaultSearchOperator })); + const shouldClauses = result.query.bool.should; + + expect(shouldClauses.length).toBe(3); + + const mppClauses = shouldClauses.slice(1); + + expect(mppClauses.map((clause: any) => clause.match_phrase_prefix)).toEqual([ + { 'saved.title': { query: 'foo', boost: 3 } }, + { 'saved.description': { query: 'foo', boost: 1 } }, + ]); }); }); }); @@ -532,7 +687,6 @@ describe('#getQueryParams', () => { it(`throws for ${type} when namespaces is an empty array`, () => { expect(() => getQueryParams({ - mappings, registry, namespaces: [], }) diff --git a/src/core/server/saved_objects/service/lib/search_dsl/query_params.ts b/src/core/server/saved_objects/service/lib/search_dsl/query_params.ts index 8d4fe13b9bede..2ecba42e408e7 100644 --- a/src/core/server/saved_objects/service/lib/search_dsl/query_params.ts +++ b/src/core/server/saved_objects/service/lib/search_dsl/query_params.ts @@ -20,7 +20,6 @@ import { esKuery } from '../../../es_query'; type KueryNode = any; -import { getRootPropertiesObjects, IndexMapping } from '../../../mappings'; import { ISavedObjectTypeRegistry } from '../../../saved_objects_type_registry'; import { ALL_NAMESPACES_STRING, DEFAULT_NAMESPACE_STRING } from '../utils'; @@ -28,22 +27,17 @@ import { ALL_NAMESPACES_STRING, DEFAULT_NAMESPACE_STRING } from '../utils'; * Gets the types based on the type. Uses mappings to support * null type (all types), a single type string or an array */ -function getTypes(mappings: IndexMapping, type?: string | string[]) { +function getTypes(registry: ISavedObjectTypeRegistry, type?: string | string[]) { if (!type) { - return Object.keys(getRootPropertiesObjects(mappings)); + return registry.getAllTypes().map((registeredType) => registeredType.name); } - - if (Array.isArray(type)) { - return type; - } - - return [type]; + return Array.isArray(type) ? type : [type]; } /** * Get the field params based on the types, searchFields, and rootSearchFields */ -function getFieldsForTypes( +function getSimpleQueryStringTypeFields( types: string[], searchFields: string[] = [], rootSearchFields: string[] = [] @@ -81,34 +75,41 @@ function getClauseForType( if (namespaces.length === 0) { throw new Error('cannot specify empty namespaces array'); } + const searchAcrossAllNamespaces = namespaces.includes(ALL_NAMESPACES_STRING); + if (registry.isMultiNamespace(type)) { + const namespacesFilterClause = searchAcrossAllNamespaces + ? {} + : { terms: { namespaces: [...namespaces, ALL_NAMESPACES_STRING] } }; + return { bool: { - must: [ - { term: { type } }, - { terms: { namespaces: [...namespaces, ALL_NAMESPACES_STRING] } }, - ], + must: [{ term: { type } }, namespacesFilterClause], must_not: [{ exists: { field: 'namespace' } }], }, }; } else if (registry.isSingleNamespace(type)) { const should: Array> = []; const eligibleNamespaces = namespaces.filter((x) => x !== DEFAULT_NAMESPACE_STRING); - if (eligibleNamespaces.length > 0) { + if (eligibleNamespaces.length > 0 && !searchAcrossAllNamespaces) { should.push({ terms: { namespace: eligibleNamespaces } }); } if (namespaces.includes(DEFAULT_NAMESPACE_STRING)) { should.push({ bool: { must_not: [{ exists: { field: 'namespace' } }] } }); } - if (should.length === 0) { - // This is indicitive of a bug, and not user error. - throw new Error('unhandled search condition: expected at least 1 `should` clause.'); - } + + const shouldClauseProps = + should.length > 0 + ? { + should, + minimum_should_match: 1, + } + : {}; + return { bool: { must: [{ term: { type } }], - should, - minimum_should_match: 1, + ...shouldClauseProps, must_not: [{ exists: { field: 'namespaces' } }], }, }; @@ -130,7 +131,6 @@ export interface HasReferenceQueryParams { export type SearchOperator = 'AND' | 'OR'; interface QueryParams { - mappings: IndexMapping; registry: ISavedObjectTypeRegistry; namespaces?: string[]; type?: string | string[]; @@ -188,11 +188,14 @@ export function getClauseForReference(reference: HasReferenceQueryParams) { }; } +// A de-duplicated set of namespaces makes for a more effecient query. +const uniqNamespaces = (namespacesToNormalize?: string[]) => + namespacesToNormalize ? Array.from(new Set(namespacesToNormalize)) : undefined; + /** * Get the "query" related keys for the search body */ export function getQueryParams({ - mappings, registry, namespaces, type, @@ -206,7 +209,7 @@ export function getQueryParams({ kueryNode, }: QueryParams) { const types = getTypes( - mappings, + registry, typeToNamespacesMap ? Array.from(typeToNamespacesMap.keys()) : type ); @@ -214,35 +217,17 @@ export function getQueryParams({ hasReference = [hasReference]; } - // A de-duplicated set of namespaces makes for a more effecient query. - // - // Additonally, we treat the `*` namespace as the `default` namespace. - // In the Default Distribution, the `*` is automatically expanded to include all available namespaces. - // However, the OSS distribution (and certain configurations of the Default Distribution) can allow the `*` - // to pass through to the SO Repository, and eventually to this module. When this happens, we translate to `default`, - // since that is consistent with how a single-namespace search behaves in the OSS distribution. Leaving the wildcard in place - // would result in no results being returned, as the wildcard is treated as a literal, and not _actually_ as a wildcard. - // We had a good discussion around the tradeoffs here: https://github.com/elastic/kibana/pull/67644#discussion_r441055716 - const normalizeNamespaces = (namespacesToNormalize?: string[]) => - namespacesToNormalize - ? Array.from( - new Set(namespacesToNormalize.map((x) => (x === '*' ? DEFAULT_NAMESPACE_STRING : x))) - ) - : undefined; - const bool: any = { filter: [ ...(kueryNode != null ? [esKuery.toElasticsearchQuery(kueryNode)] : []), - ...(hasReference && hasReference.length - ? [getReferencesFilter(hasReference, hasReferenceOperator)] - : []), + ...(hasReference?.length ? [getReferencesFilter(hasReference, hasReferenceOperator)] : []), { bool: { should: types.map((shouldType) => { - const normalizedNamespaces = normalizeNamespaces( + const deduplicatedNamespaces = uniqNamespaces( typeToNamespacesMap ? typeToNamespacesMap.get(shouldType) : namespaces ); - return getClauseForType(registry, normalizedNamespaces, shouldType); + return getClauseForType(registry, deduplicatedNamespaces, shouldType); }), minimum_should_match: 1, }, @@ -251,16 +236,133 @@ export function getQueryParams({ }; if (search) { - bool.must = [ - { - simple_query_string: { - query: search, - ...getFieldsForTypes(types, searchFields, rootSearchFields), - ...(defaultSearchOperator ? { default_operator: defaultSearchOperator } : {}), - }, - }, - ]; + const useMatchPhrasePrefix = shouldUseMatchPhrasePrefix(search); + const simpleQueryStringClause = getSimpleQueryStringClause({ + search, + types, + searchFields, + rootSearchFields, + defaultSearchOperator, + }); + + if (useMatchPhrasePrefix) { + bool.should = [ + simpleQueryStringClause, + ...getMatchPhrasePrefixClauses({ search, searchFields, types, registry }), + ]; + bool.minimum_should_match = 1; + } else { + bool.must = [simpleQueryStringClause]; + } } return { query: { bool } }; } + +// we only want to add match_phrase_prefix clauses +// if the search is a prefix search +const shouldUseMatchPhrasePrefix = (search: string): boolean => { + return search.trim().endsWith('*'); +}; + +const getMatchPhrasePrefixClauses = ({ + search, + searchFields, + registry, + types, +}: { + search: string; + searchFields?: string[]; + types: string[]; + registry: ISavedObjectTypeRegistry; +}) => { + // need to remove the prefix search operator + const query = search.replace(/[*]$/, ''); + const mppFields = getMatchPhrasePrefixFields({ searchFields, types, registry }); + return mppFields.map(({ field, boost }) => { + return { + match_phrase_prefix: { + [field]: { + query, + boost, + }, + }, + }; + }); +}; + +interface FieldWithBoost { + field: string; + boost?: number; +} + +const getMatchPhrasePrefixFields = ({ + searchFields = [], + types, + registry, +}: { + searchFields?: string[]; + types: string[]; + registry: ISavedObjectTypeRegistry; +}): FieldWithBoost[] => { + const output: FieldWithBoost[] = []; + + searchFields = searchFields.filter((field) => field !== '*'); + let fields: string[]; + if (searchFields.length === 0) { + fields = types.reduce((typeFields, type) => { + const defaultSearchField = registry.getType(type)?.management?.defaultSearchField; + if (defaultSearchField) { + return [...typeFields, `${type}.${defaultSearchField}`]; + } + return typeFields; + }, [] as string[]); + } else { + fields = []; + for (const field of searchFields) { + fields = fields.concat(types.map((type) => `${type}.${field}`)); + } + } + + fields.forEach((rawField) => { + const [field, rawBoost] = rawField.split('^'); + let boost: number = 1; + if (rawBoost) { + try { + boost = parseInt(rawBoost, 10); + } catch (e) { + boost = 1; + } + } + if (isNaN(boost)) { + boost = 1; + } + output.push({ + field, + boost, + }); + }); + return output; +}; + +const getSimpleQueryStringClause = ({ + search, + types, + searchFields, + rootSearchFields, + defaultSearchOperator, +}: { + search: string; + types: string[]; + searchFields?: string[]; + rootSearchFields?: string[]; + defaultSearchOperator?: SearchOperator; +}) => { + return { + simple_query_string: { + query: search, + ...getSimpleQueryStringTypeFields(types, searchFields, rootSearchFields), + ...(defaultSearchOperator ? { default_operator: defaultSearchOperator } : {}), + }, + }; +}; diff --git a/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.test.ts b/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.test.ts index a9f26f71a3f2b..3522ab9ef1736 100644 --- a/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.test.ts +++ b/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.test.ts @@ -76,7 +76,6 @@ describe('getSearchDsl', () => { getSearchDsl(mappings, registry, opts); expect(getQueryParams).toHaveBeenCalledTimes(1); expect(getQueryParams).toHaveBeenCalledWith({ - mappings, registry, namespaces: opts.namespaces, type: opts.type, diff --git a/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.ts b/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.ts index d5da82e5617be..bddecc4d7f649 100644 --- a/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.ts +++ b/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.ts @@ -71,7 +71,6 @@ export function getSearchDsl( return { ...getQueryParams({ - mappings, registry, namespaces, type, diff --git a/src/dev/build/tasks/bin/scripts/kibana b/src/dev/build/tasks/bin/scripts/kibana index c606436c7b83f..a4fc5385500b5 100755 --- a/src/dev/build/tasks/bin/scripts/kibana +++ b/src/dev/build/tasks/bin/scripts/kibana @@ -14,7 +14,7 @@ while [ -h "$SCRIPT" ] ; do done DIR="$(dirname "${SCRIPT}")/.." -CONFIG_DIR=${KIBANA_PATH_CONF:-"$DIR/config"} +CONFIG_DIR=${KBN_PATH_CONF:-"$DIR/config"} NODE="${DIR}/node/bin/node" test -x "$NODE" if [ ! -x "$NODE" ]; then diff --git a/src/dev/build/tasks/os_packages/package_scripts/post_install.sh b/src/dev/build/tasks/os_packages/package_scripts/post_install.sh index 939226b565f79..728278dae746b 100644 --- a/src/dev/build/tasks/os_packages/package_scripts/post_install.sh +++ b/src/dev/build/tasks/os_packages/package_scripts/post_install.sh @@ -1,6 +1,11 @@ #!/bin/sh set -e +# source the default env file +if [ -f "<%= envFile %>" ]; then + . "<%= envFile %>" +fi + export KBN_PATH_CONF=${KBN_PATH_CONF:-<%= configDir %>} set_chmod() { @@ -71,4 +76,12 @@ if [ "$IS_UPGRADE" = "true" ]; then if command -v systemctl >/dev/null; then systemctl daemon-reload fi + + if [ "$RESTART_ON_UPGRADE" = "true" ]; then + echo -n "Restarting kibana service..." + if command -v systemctl >/dev/null; then + systemctl restart kibana.service || true + fi + echo " OK" + fi fi diff --git a/src/dev/build/tasks/os_packages/run_fpm.ts b/src/dev/build/tasks/os_packages/run_fpm.ts index e5de760ea11d0..f16eaea1daa2f 100644 --- a/src/dev/build/tasks/os_packages/run_fpm.ts +++ b/src/dev/build/tasks/os_packages/run_fpm.ts @@ -111,7 +111,8 @@ export async function runFpm( `dataDir=/var/lib/kibana`, '--template-value', `logDir=/var/log/kibana`, - + '--template-value', + `envFile=/etc/default/kibana`, // config and data directories are copied to /usr/share and /var/lib // below, so exclude them from the main package source located in // /usr/share/kibana/config. PATHS MUST BE RELATIVE, so drop the leading slash diff --git a/src/dev/build/tasks/os_packages/service_templates/systemd/etc/default/kibana b/src/dev/build/tasks/os_packages/service_templates/systemd/etc/default/kibana index 9c9f58ded350b..7d0c955964ae6 100644 --- a/src/dev/build/tasks/os_packages/service_templates/systemd/etc/default/kibana +++ b/src/dev/build/tasks/os_packages/service_templates/systemd/etc/default/kibana @@ -1,13 +1,5 @@ user="kibana" group="kibana" -chroot="/" -chdir="/" -nice="" - - -# If this is set to 1, then when `stop` is called, if the process has -# not exited within a reasonable time, SIGKILL will be sent next. -# The default behavior is to simply log a message "program stop failed; still running" -KILL_ON_STOP_TIMEOUT=0 KBN_PATH_CONF="/etc/kibana" +RESTART_ON_UPGRADE="true" diff --git a/src/dev/build/tasks/os_packages/service_templates/systemd/etc/systemd/system/kibana.service b/src/dev/build/tasks/os_packages/service_templates/systemd/etc/systemd/system/kibana.service index 05724db8799f3..7a1508d91b213 100644 --- a/src/dev/build/tasks/os_packages/service_templates/systemd/etc/systemd/system/kibana.service +++ b/src/dev/build/tasks/os_packages/service_templates/systemd/etc/systemd/system/kibana.service @@ -15,7 +15,7 @@ Environment=KBN_PATH_CONF=/etc/kibana EnvironmentFile=-/etc/default/kibana EnvironmentFile=-/etc/sysconfig/kibana -ExecStart=/usr/share/kibana/bin/kibana --logging.dest="/var/log/kibana/kibana.log" +ExecStart=/usr/share/kibana/bin/kibana --logging.dest="/var/log/kibana/kibana.log" --pid.file="/run/kibana/kibana.pid" Restart=on-failure RestartSec=3 diff --git a/src/dev/build/tasks/os_packages/service_templates/systemd/usr/lib/tmpfiles.d/kibana.conf b/src/dev/build/tasks/os_packages/service_templates/systemd/usr/lib/tmpfiles.d/kibana.conf index b5422df52fe11..fe033e30fbf58 100644 --- a/src/dev/build/tasks/os_packages/service_templates/systemd/usr/lib/tmpfiles.d/kibana.conf +++ b/src/dev/build/tasks/os_packages/service_templates/systemd/usr/lib/tmpfiles.d/kibana.conf @@ -1 +1 @@ -d /var/run/kibana 0755 kibana kibana - - \ No newline at end of file +d /run/kibana 0755 kibana kibana - - \ No newline at end of file diff --git a/src/plugins/data/common/index_patterns/index_patterns/index_pattern.test.ts b/src/plugins/data/common/index_patterns/index_patterns/index_pattern.test.ts index 9085ae07bbe3e..145901509d1c5 100644 --- a/src/plugins/data/common/index_patterns/index_patterns/index_pattern.test.ts +++ b/src/plugins/data/common/index_patterns/index_patterns/index_pattern.test.ts @@ -196,6 +196,24 @@ describe('IndexPattern', () => { }); }); + describe('getFormatterForField', () => { + test('should return the default one for empty objects', () => { + indexPattern.setFieldFormat('scriptedFieldWithEmptyFormatter', {}); + expect( + indexPattern.getFormatterForField({ + name: 'scriptedFieldWithEmptyFormatter', + type: 'number', + esTypes: ['long'], + }) + ).toEqual( + expect.objectContaining({ + convert: expect.any(Function), + getConverterFor: expect.any(Function), + }) + ); + }); + }); + describe('toSpec', () => { test('should match snapshot', () => { const formatter = { diff --git a/src/plugins/data/common/index_patterns/index_patterns/index_pattern.ts b/src/plugins/data/common/index_patterns/index_patterns/index_pattern.ts index a0f27078543a9..4508d7b1d9082 100644 --- a/src/plugins/data/common/index_patterns/index_patterns/index_pattern.ts +++ b/src/plugins/data/common/index_patterns/index_patterns/index_pattern.ts @@ -291,15 +291,15 @@ export class IndexPattern implements IIndexPattern { getFormatterForField( field: IndexPatternField | IndexPatternField['spec'] | IFieldType ): FieldFormat { - const formatSpec = this.fieldFormatMap[field.name]; - if (formatSpec) { - return this.fieldFormats.getInstance(formatSpec.id, formatSpec.params); - } else { - return this.fieldFormats.getDefaultInstance( - field.type as KBN_FIELD_TYPES, - field.esTypes as ES_FIELD_TYPES[] - ); + const fieldFormat = this.getFormatterForFieldNoDefault(field.name); + if (fieldFormat) { + return fieldFormat; } + + return this.fieldFormats.getDefaultInstance( + field.type as KBN_FIELD_TYPES, + field.esTypes as ES_FIELD_TYPES[] + ); } /** @@ -308,7 +308,7 @@ export class IndexPattern implements IIndexPattern { */ getFormatterForFieldNoDefault(fieldname: string) { const formatSpec = this.fieldFormatMap[fieldname]; - if (formatSpec) { + if (formatSpec?.id) { return this.fieldFormats.getInstance(formatSpec.id, formatSpec.params); } } diff --git a/src/plugins/data/common/index_patterns/index_patterns/index_patterns.ts b/src/plugins/data/common/index_patterns/index_patterns/index_patterns.ts index aae9b89cdc61f..19c6e9c7b8a7a 100644 --- a/src/plugins/data/common/index_patterns/index_patterns/index_patterns.ts +++ b/src/plugins/data/common/index_patterns/index_patterns/index_patterns.ts @@ -98,11 +98,12 @@ export class IndexPatternsService { * Refresh cache of index pattern ids and titles */ private async refreshSavedObjectsCache() { - this.savedObjectsCache = await this.savedObjectsClient.find({ + const so = await this.savedObjectsClient.find({ type: 'index-pattern', fields: ['title'], perPage: 10000, }); + this.savedObjectsCache = so; } /** @@ -215,13 +216,13 @@ export class IndexPatternsService { * Get field list by providing { pattern } * @param options */ - getFieldsForWildcard = async (options: GetFieldsOptions = {}) => { + getFieldsForWildcard = async (options: GetFieldsOptions) => { const metaFields = await this.config.get(UI_SETTINGS.META_FIELDS); return this.apiClient.getFieldsForWildcard({ pattern: options.pattern, metaFields, type: options.type, - params: options.params || {}, + rollupIndex: options.rollupIndex, }); }; @@ -231,13 +232,13 @@ export class IndexPatternsService { */ getFieldsForIndexPattern = async ( indexPattern: IndexPattern | IndexPatternSpec, - options: GetFieldsOptions = {} + options?: GetFieldsOptions ) => this.getFieldsForWildcard({ - pattern: indexPattern.title as string, - ...options, type: indexPattern.type, - params: indexPattern.typeMeta && indexPattern.typeMeta.params, + rollupIndex: indexPattern?.typeMeta?.params?.rollup_index, + ...options, + pattern: indexPattern.title as string, }); /** @@ -374,10 +375,10 @@ export class IndexPatternsService { try { spec.fields = isFieldRefreshRequired ? await this.refreshFieldSpecMap(spec.fields || {}, id, spec.title as string, { - pattern: title, + pattern: title as string, metaFields: await this.config.get(UI_SETTINGS.META_FIELDS), type, - params: typeMeta && typeMeta.params, + rollupIndex: typeMeta?.params?.rollupIndex, }) : spec.fields; } catch (err) { diff --git a/src/plugins/data/common/index_patterns/types.ts b/src/plugins/data/common/index_patterns/types.ts index 3387bc3b3c19e..b381cc0963333 100644 --- a/src/plugins/data/common/index_patterns/types.ts +++ b/src/plugins/data/common/index_patterns/types.ts @@ -86,15 +86,22 @@ export interface SavedObjectsClientCommon { } export interface GetFieldsOptions { - pattern?: string; + pattern: string; type?: string; - params?: any; lookBack?: boolean; metaFields?: string[]; + rollupIndex?: string; +} + +export interface GetFieldsOptionsTimePattern { + pattern: string; + metaFields: string[]; + lookBack: number; + interval: string; } export interface IIndexPatternsApiClient { - getFieldsForTimePattern: (options: GetFieldsOptions) => Promise; + getFieldsForTimePattern: (options: GetFieldsOptionsTimePattern) => Promise; getFieldsForWildcard: (options: GetFieldsOptions) => Promise; } diff --git a/src/plugins/data/common/search/aggs/agg_config.test.ts b/src/plugins/data/common/search/aggs/agg_config.test.ts index f6fcc29805dc4..9bb47f5cb3575 100644 --- a/src/plugins/data/common/search/aggs/agg_config.test.ts +++ b/src/plugins/data/common/search/aggs/agg_config.test.ts @@ -680,16 +680,6 @@ describe('AggConfig', () => { const json = aggConfig.toExpressionAst()?.arguments.json; expect(json).toEqual([JSON.stringify(configStates.params.json)]); }); - - it(`returns undefined if an expressionName doesn't exist on the agg type`, () => { - const ac = new AggConfigs(indexPattern, [], { typesRegistry }); - const configStates = { - type: 'unknown type', - params: {}, - }; - const aggConfig = ac.createAggConfig(configStates); - expect(aggConfig.toExpressionAst()).toBe(undefined); - }); }); describe('#makeLabel', () => { diff --git a/src/plugins/data/common/search/aggs/agg_configs.test.ts b/src/plugins/data/common/search/aggs/agg_configs.test.ts index 803ccc70b98a7..d1c8e29a03cc7 100644 --- a/src/plugins/data/common/search/aggs/agg_configs.test.ts +++ b/src/plugins/data/common/search/aggs/agg_configs.test.ts @@ -150,6 +150,27 @@ describe('AggConfigs', () => { ); expect(ac.aggs).toHaveLength(1); }); + + it(`throws if trying to add an agg which doesn't have a type in the registry`, () => { + const configStates = [ + { + enabled: true, + type: 'histogram', + params: {}, + }, + ]; + + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); + expect(() => + ac.createAggConfig({ + enabled: true, + type: 'oops', + params: {}, + }) + ).toThrowErrorMatchingInlineSnapshot( + `"Unable to find a registered agg type for \\"oops\\"."` + ); + }); }); describe('#getRequestAggs', () => { diff --git a/src/plugins/data/common/search/aggs/agg_configs.ts b/src/plugins/data/common/search/aggs/agg_configs.ts index 282e6f3b538a4..368f44f161132 100644 --- a/src/plugins/data/common/search/aggs/agg_configs.ts +++ b/src/plugins/data/common/search/aggs/agg_configs.ts @@ -18,6 +18,7 @@ */ import _ from 'lodash'; +import { i18n } from '@kbn/i18n'; import { Assign } from '@kbn/utility-types'; import { ISearchOptions, ISearchSource } from 'src/plugins/data/public'; @@ -122,15 +123,29 @@ export class AggConfigs { { addToAggConfigs = true } = {} ) => { const { type } = params; - let aggConfig; + const getType = (t: string) => { + const typeFromRegistry = this.typesRegistry.get(t); + + if (!typeFromRegistry) { + throw new Error( + i18n.translate('data.search.aggs.error.aggNotFound', { + defaultMessage: 'Unable to find a registered agg type for "{type}".', + values: { type: type as string }, + }) + ); + } + return typeFromRegistry; + }; + + let aggConfig; if (params instanceof AggConfig) { aggConfig = params; params.parent = this; } else { aggConfig = new AggConfig(this, { ...params, - type: typeof type === 'string' ? this.typesRegistry.get(type) : type, + type: typeof type === 'string' ? getType(type) : type, }); } diff --git a/src/plugins/expressions/common/expression_functions/specs/tests/__snapshots__/kibana.test.ts.snap b/src/plugins/data/common/search/expressions/__snapshots__/kibana.test.ts.snap similarity index 100% rename from src/plugins/expressions/common/expression_functions/specs/tests/__snapshots__/kibana.test.ts.snap rename to src/plugins/data/common/search/expressions/__snapshots__/kibana.test.ts.snap diff --git a/src/plugins/data/common/search/expressions/esaggs.ts b/src/plugins/data/common/search/expressions/esaggs.ts index 4f65babdcd360..47d97a81a67b1 100644 --- a/src/plugins/data/common/search/expressions/esaggs.ts +++ b/src/plugins/data/common/search/expressions/esaggs.ts @@ -17,11 +17,8 @@ * under the License. */ -import { - KibanaContext, - Datatable, - ExpressionFunctionDefinition, -} from '../../../../../plugins/expressions/common'; +import { Datatable, ExpressionFunctionDefinition } from 'src/plugins/expressions/common'; +import { KibanaContext } from './kibana_context_type'; type Input = KibanaContext | null; type Output = Promise; diff --git a/src/plugins/data/common/search/expressions/index.ts b/src/plugins/data/common/search/expressions/index.ts index 25839a805d8c5..28d892d091956 100644 --- a/src/plugins/data/common/search/expressions/index.ts +++ b/src/plugins/data/common/search/expressions/index.ts @@ -17,5 +17,8 @@ * under the License. */ +export * from './kibana'; +export * from './kibana_context'; +export * from './kibana_context_type'; export * from './esaggs'; export * from './utils'; diff --git a/src/plugins/expressions/common/expression_functions/specs/tests/kibana.test.ts b/src/plugins/data/common/search/expressions/kibana.test.ts similarity index 92% rename from src/plugins/expressions/common/expression_functions/specs/tests/kibana.test.ts rename to src/plugins/data/common/search/expressions/kibana.test.ts index e5c4b92de4fdb..58fee1ee1f6a6 100644 --- a/src/plugins/expressions/common/expression_functions/specs/tests/kibana.test.ts +++ b/src/plugins/data/common/search/expressions/kibana.test.ts @@ -17,14 +17,14 @@ * under the License. */ +import { ExecutionContext } from 'src/plugins/expressions/common'; +import { kibana } from './kibana'; +import { ExpressionValueSearchContext } from './kibana_context_type'; import { functionWrapper } from './utils'; -import { kibana } from '../kibana'; -import { ExecutionContext } from '../../../execution/types'; -import { KibanaContext, ExpressionValueSearchContext } from '../../../expression_types'; describe('interpreter/functions#kibana', () => { const fn = functionWrapper(kibana); - let input: Partial; + let input: Partial; let search: ExpressionValueSearchContext; let context: ExecutionContext; diff --git a/src/plugins/expressions/common/expression_functions/specs/kibana.ts b/src/plugins/data/common/search/expressions/kibana.ts similarity index 82% rename from src/plugins/expressions/common/expression_functions/specs/kibana.ts rename to src/plugins/data/common/search/expressions/kibana.ts index 3ec4c23eab28d..c31219284760a 100644 --- a/src/plugins/expressions/common/expression_functions/specs/kibana.ts +++ b/src/plugins/data/common/search/expressions/kibana.ts @@ -18,8 +18,9 @@ */ import { i18n } from '@kbn/i18n'; -import { ExpressionFunctionDefinition } from '../types'; -import { ExpressionValueSearchContext } from '../../expression_types'; +import { ExecutionContext, ExpressionFunctionDefinition } from 'src/plugins/expressions/common'; +import { Adapters } from 'src/plugins/inspector/common'; +import { ExpressionValueSearchContext, ExecutionContextSearch } from './kibana_context_type'; const toArray = (query: undefined | T | T[]): T[] => !query ? [] : Array.isArray(query) ? query : [query]; @@ -29,7 +30,8 @@ export type ExpressionFunctionKibana = ExpressionFunctionDefinition< // TODO: Get rid of the `null` type below. ExpressionValueSearchContext | null, object, - ExpressionValueSearchContext + ExpressionValueSearchContext, + ExecutionContext >; export const kibana: ExpressionFunctionKibana = { @@ -38,7 +40,7 @@ export const kibana: ExpressionFunctionKibana = { inputTypes: ['kibana_context', 'null'], - help: i18n.translate('expressions.functions.kibana.help', { + help: i18n.translate('data.search.functions.kibana.help', { defaultMessage: 'Gets kibana global context', }), diff --git a/src/plugins/expressions/common/expression_functions/specs/kibana_context.ts b/src/plugins/data/common/search/expressions/kibana_context.ts similarity index 84% rename from src/plugins/expressions/common/expression_functions/specs/kibana_context.ts rename to src/plugins/data/common/search/expressions/kibana_context.ts index 2b7d1b8ed9d76..7bf14ff02316e 100644 --- a/src/plugins/expressions/common/expression_functions/specs/kibana_context.ts +++ b/src/plugins/data/common/search/expressions/kibana_context.ts @@ -16,11 +16,13 @@ * specific language governing permissions and limitations * under the License. */ + import { uniqBy } from 'lodash'; import { i18n } from '@kbn/i18n'; -import { ExpressionFunctionDefinition } from '../../expression_functions'; -import { KibanaContext } from '../../expression_types'; -import { Query, uniqFilters } from '../../../../data/common'; +import { ExpressionFunctionDefinition, ExecutionContext } from 'src/plugins/expressions/common'; +import { Adapters } from 'src/plugins/inspector/common'; +import { Query, uniqFilters } from '../../query'; +import { ExecutionContextSearch, KibanaContext } from './kibana_context_type'; interface Arguments { q?: string | null; @@ -33,7 +35,8 @@ export type ExpressionFunctionKibanaContext = ExpressionFunctionDefinition< 'kibana_context', KibanaContext | null, Arguments, - Promise + Promise, + ExecutionContext >; const getParsedValue = (data: any, defaultValue: any) => @@ -49,7 +52,7 @@ export const kibanaContextFunction: ExpressionFunctionKibanaContext = { name: 'kibana_context', type: 'kibana_context', inputTypes: ['kibana_context', 'null'], - help: i18n.translate('expressions.functions.kibana_context.help', { + help: i18n.translate('data.search.functions.kibana_context.help', { defaultMessage: 'Updates kibana global context', }), args: { @@ -57,28 +60,28 @@ export const kibanaContextFunction: ExpressionFunctionKibanaContext = { types: ['string', 'null'], aliases: ['query', '_'], default: null, - help: i18n.translate('expressions.functions.kibana_context.q.help', { + help: i18n.translate('data.search.functions.kibana_context.q.help', { defaultMessage: 'Specify Kibana free form text query', }), }, filters: { types: ['string', 'null'], default: '"[]"', - help: i18n.translate('expressions.functions.kibana_context.filters.help', { + help: i18n.translate('data.search.functions.kibana_context.filters.help', { defaultMessage: 'Specify Kibana generic filters', }), }, timeRange: { types: ['string', 'null'], default: null, - help: i18n.translate('expressions.functions.kibana_context.timeRange.help', { + help: i18n.translate('data.search.functions.kibana_context.timeRange.help', { defaultMessage: 'Specify Kibana time range filter', }), }, savedSearchId: { types: ['string', 'null'], default: null, - help: i18n.translate('expressions.functions.kibana_context.savedSearchId.help', { + help: i18n.translate('data.search.functions.kibana_context.savedSearchId.help', { defaultMessage: 'Specify saved search ID to be used for queries and filters', }), }, diff --git a/src/plugins/expressions/common/expression_types/specs/kibana_context.ts b/src/plugins/data/common/search/expressions/kibana_context_type.ts similarity index 79% rename from src/plugins/expressions/common/expression_types/specs/kibana_context.ts rename to src/plugins/data/common/search/expressions/kibana_context_type.ts index 3af7b990429c0..a5b459a607991 100644 --- a/src/plugins/expressions/common/expression_types/specs/kibana_context.ts +++ b/src/plugins/data/common/search/expressions/kibana_context_type.ts @@ -17,8 +17,16 @@ * under the License. */ -import { ExpressionValueBoxed } from '../types'; -import { ExecutionContextSearch } from '../../execution/types'; +import { ExpressionValueBoxed } from 'src/plugins/expressions/common'; +import { Filter } from '../../es_query'; +import { Query, TimeRange } from '../../query'; + +// eslint-disable-next-line @typescript-eslint/consistent-type-definitions +export type ExecutionContextSearch = { + filters?: Filter[]; + query?: Query | Query[]; + timeRange?: TimeRange; +}; export type ExpressionValueSearchContext = ExpressionValueBoxed< 'kibana_context', diff --git a/src/plugins/data/common/search/expressions/utils/function_wrapper.ts b/src/plugins/data/common/search/expressions/utils/function_wrapper.ts new file mode 100644 index 0000000000000..b5e45d9ca1de0 --- /dev/null +++ b/src/plugins/data/common/search/expressions/utils/function_wrapper.ts @@ -0,0 +1,34 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { mapValues } from 'lodash'; +import { AnyExpressionFunctionDefinition, ExecutionContext } from 'src/plugins/expressions/common'; + +/** + * Takes a function spec and passes in default args, + * overriding with any provided args. + */ +export const functionWrapper = (spec: AnyExpressionFunctionDefinition) => { + const defaultArgs = mapValues(spec.args, (argSpec) => argSpec.default); + return ( + context: object | null, + args: Record = {}, + handlers: ExecutionContext = {} as ExecutionContext + ) => spec.fn(context, { ...defaultArgs, ...args }, handlers); +}; diff --git a/src/plugins/data/common/search/expressions/utils/index.ts b/src/plugins/data/common/search/expressions/utils/index.ts index 75c1809770c78..39f88b0f13fee 100644 --- a/src/plugins/data/common/search/expressions/utils/index.ts +++ b/src/plugins/data/common/search/expressions/utils/index.ts @@ -18,3 +18,4 @@ */ export * from './courier_inspector_stats'; +export * from './function_wrapper'; diff --git a/src/plugins/data/common/utils/index.ts b/src/plugins/data/common/utils/index.ts index 33989f3ad50a7..8b8686c51b9c1 100644 --- a/src/plugins/data/common/utils/index.ts +++ b/src/plugins/data/common/utils/index.ts @@ -19,4 +19,3 @@ /** @internal */ export { shortenDottedString } from './shorten_dotted_string'; -export { AbortError, toPromise, getCombinedSignal } from './abort_utils'; diff --git a/src/plugins/data/kibana.json b/src/plugins/data/kibana.json index 9cb9b1745373a..d6f2534bd5e3b 100644 --- a/src/plugins/data/kibana.json +++ b/src/plugins/data/kibana.json @@ -8,7 +8,7 @@ "uiActions" ], "optionalPlugins": ["usageCollection"], - "extraPublicDirs": ["common", "common/utils/abort_utils"], + "extraPublicDirs": ["common"], "requiredBundles": [ "usageCollection", "kibanaUtils", diff --git a/src/plugins/data/public/index.ts b/src/plugins/data/public/index.ts index ce020a9742399..129addf3de70e 100644 --- a/src/plugins/data/public/index.ts +++ b/src/plugins/data/public/index.ts @@ -338,6 +338,12 @@ export { OptionedParamType, OptionedValueProp, ParsedInterval, + // expressions + ExecutionContextSearch, + ExpressionFunctionKibana, + ExpressionFunctionKibanaContext, + ExpressionValueSearchContext, + KibanaContext, // tabify TabbedAggColumn, TabbedAggRow, diff --git a/src/plugins/data/public/index_patterns/index_patterns/index_patterns_api_client.test.ts b/src/plugins/data/public/index_patterns/index_patterns/index_patterns_api_client.test.ts index 37ee80c2c29e4..8c48ee44fba9c 100644 --- a/src/plugins/data/public/index_patterns/index_patterns/index_patterns_api_client.test.ts +++ b/src/plugins/data/public/index_patterns/index_patterns/index_patterns_api_client.test.ts @@ -32,7 +32,12 @@ describe('IndexPatternsApiClient', () => { test('uses the right URI to fetch fields for time patterns', async function () { const expectedPath = '/api/index_patterns/_fields_for_time_pattern'; - await indexPatternsApiClient.getFieldsForTimePattern(); + await indexPatternsApiClient.getFieldsForTimePattern({ + pattern: 'blah', + metaFields: [], + lookBack: 5, + interval: '', + }); expect(fetchSpy).toHaveBeenCalledWith(expectedPath, expect.any(Object)); }); @@ -40,15 +45,7 @@ describe('IndexPatternsApiClient', () => { test('uses the right URI to fetch fields for wildcard', async function () { const expectedPath = '/api/index_patterns/_fields_for_wildcard'; - await indexPatternsApiClient.getFieldsForWildcard(); - - expect(fetchSpy).toHaveBeenCalledWith(expectedPath, expect.any(Object)); - }); - - test('uses the right URI to fetch fields for wildcard given a type', async function () { - const expectedPath = '/api/index_patterns/rollup/_fields_for_wildcard'; - - await indexPatternsApiClient.getFieldsForWildcard({ type: 'rollup' }); + await indexPatternsApiClient.getFieldsForWildcard({ pattern: 'blah' }); expect(fetchSpy).toHaveBeenCalledWith(expectedPath, expect.any(Object)); }); diff --git a/src/plugins/data/public/index_patterns/index_patterns/index_patterns_api_client.ts b/src/plugins/data/public/index_patterns/index_patterns/index_patterns_api_client.ts index 377a3f7f91a50..ca0f35d6612b2 100644 --- a/src/plugins/data/public/index_patterns/index_patterns/index_patterns_api_client.ts +++ b/src/plugins/data/public/index_patterns/index_patterns/index_patterns_api_client.ts @@ -19,7 +19,11 @@ import { HttpSetup } from 'src/core/public'; import { IndexPatternMissingIndices } from '../../../common/index_patterns/lib'; -import { GetFieldsOptions, IIndexPatternsApiClient } from '../../../common/index_patterns/types'; +import { + GetFieldsOptions, + IIndexPatternsApiClient, + GetFieldsOptionsTimePattern, +} from '../../../common/index_patterns/types'; const API_BASE_URL: string = `/api/index_patterns/`; @@ -48,7 +52,7 @@ export class IndexPatternsApiClient implements IIndexPatternsApiClient { return API_BASE_URL + path.filter(Boolean).map(encodeURIComponent).join('/'); } - getFieldsForTimePattern(options: GetFieldsOptions = {}) { + getFieldsForTimePattern(options: GetFieldsOptionsTimePattern) { const { pattern, lookBack, metaFields } = options; const url = this._getUrl(['_fields_for_time_pattern']); @@ -60,27 +64,12 @@ export class IndexPatternsApiClient implements IIndexPatternsApiClient { }).then((resp: any) => resp.fields); } - getFieldsForWildcard(options: GetFieldsOptions = {}) { - const { pattern, metaFields, type, params } = options; - - let url; - let query; - - if (type) { - url = this._getUrl([type, '_fields_for_wildcard']); - query = { - pattern, - meta_fields: metaFields, - params: JSON.stringify(params), - }; - } else { - url = this._getUrl(['_fields_for_wildcard']); - query = { - pattern, - meta_fields: metaFields, - }; - } - - return this._request(url, query).then((resp: any) => resp.fields); + getFieldsForWildcard({ pattern, metaFields, type, rollupIndex }: GetFieldsOptions) { + return this._request(this._getUrl(['_fields_for_wildcard']), { + pattern, + meta_fields: metaFields, + type, + rollup_index: rollupIndex, + }).then((resp: any) => resp.fields); } } diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index d52edbe5b11dd..31b05bd4763a2 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -6,6 +6,7 @@ import { $Values } from '@kbn/utility-types'; import { Action } from 'history'; +import { Adapters as Adapters_2 } from 'src/plugins/inspector/common'; import { ApiResponse } from '@elastic/elasticsearch'; import { ApiResponse as ApiResponse_2 } from '@elastic/elasticsearch/lib/Transport'; import { ApplicationStart } from 'kibana/public'; @@ -16,6 +17,7 @@ import { CoreSetup } from 'src/core/public'; import { CoreSetup as CoreSetup_2 } from 'kibana/public'; import { CoreStart } from 'kibana/public'; import { CoreStart as CoreStart_2 } from 'src/core/public'; +import { Datatable as Datatable_2 } from 'src/plugins/expressions/common'; import { DatatableColumn as DatatableColumn_2 } from 'src/plugins/expressions'; import { Ensure } from '@kbn/utility-types'; import { EnvironmentMode } from '@kbn/config'; @@ -26,8 +28,12 @@ import { EuiComboBoxProps } from '@elastic/eui'; import { EuiConfirmModalProps } from '@elastic/eui'; import { EuiGlobalToastListToast } from '@elastic/eui'; import { ExclusiveUnion } from '@elastic/eui'; +import { ExecutionContext } from 'src/plugins/expressions/common'; import { ExpressionAstFunction } from 'src/plugins/expressions/common'; +import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common'; +import { ExpressionFunctionDefinition as ExpressionFunctionDefinition_2 } from 'src/plugins/expressions/public'; import { ExpressionsSetup } from 'src/plugins/expressions/public'; +import { ExpressionValueBoxed } from 'src/plugins/expressions/common'; import { History } from 'history'; import { Href } from 'history'; import { IconType } from '@elastic/eui'; @@ -65,7 +71,7 @@ import { Required } from '@kbn/utility-types'; import * as Rx from 'rxjs'; import { SavedObject } from 'src/core/server'; import { SavedObject as SavedObject_2 } from 'src/core/public'; -import { SavedObjectReference as SavedObjectReference_2 } from 'src/core/types'; +import { SavedObjectReference } from 'src/core/types'; import { SavedObjectsClientContract } from 'src/core/public'; import { Search } from '@elastic/elasticsearch/api/requestParams'; import { SearchResponse } from 'elasticsearch'; @@ -80,7 +86,6 @@ import { UiActionsSetup } from 'src/plugins/ui_actions/public'; import { UiActionsStart } from 'src/plugins/ui_actions/public'; import { Unit } from '@elastic/datemath'; import { UnregisterCallback } from 'history'; -import { UnwrapPromiseOrReturn } from '@kbn/utility-types'; import { UserProvidedValues } from 'src/core/server/types'; // Warning: (ae-missing-release-tag) "ACTION_GLOBAL_APPLY_FILTER" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) @@ -525,7 +530,6 @@ export enum ES_FIELD_TYPES { // @public (undocumented) export const ES_SEARCH_STRATEGY = "es"; -// Warning: (ae-forgotten-export) The symbol "ExpressionFunctionDefinition" needs to be exported by the entry point index.d.ts // Warning: (ae-forgotten-export) The symbol "Input" needs to be exported by the entry point index.d.ts // Warning: (ae-forgotten-export) The symbol "Arguments" needs to be exported by the entry point index.d.ts // Warning: (ae-forgotten-export) The symbol "Output" needs to be exported by the entry point index.d.ts @@ -541,7 +545,7 @@ export type EsaggsExpressionFunctionDefinition = ExpressionFunctionDefinition<'e // Warning: (ae-missing-release-tag) "EsdslExpressionFunctionDefinition" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export type EsdslExpressionFunctionDefinition = ExpressionFunctionDefinition; +export type EsdslExpressionFunctionDefinition = ExpressionFunctionDefinition_2; // Warning: (ae-missing-release-tag) "esFilters" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -647,6 +651,15 @@ export type EsQuerySortValue = Record; +// Warning: (ae-missing-release-tag) "ExecutionContextSearch" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ExecutionContextSearch = { + filters?: Filter[]; + query?: Query | Query[]; + timeRange?: TimeRange; +}; + // Warning: (ae-missing-release-tag) "ExistsFilter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -655,12 +668,28 @@ export type ExistsFilter = Filter & { exists?: FilterExistsProperty; }; +// Warning: (ae-missing-release-tag) "ExpressionFunctionKibana" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ExpressionFunctionKibana = ExpressionFunctionDefinition<'kibana', ExpressionValueSearchContext | null, object, ExpressionValueSearchContext, ExecutionContext>; + +// Warning: (ae-forgotten-export) The symbol "Arguments" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "ExpressionFunctionKibanaContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ExpressionFunctionKibanaContext = ExpressionFunctionDefinition<'kibana_context', KibanaContext | null, Arguments_2, Promise, ExecutionContext>; + +// Warning: (ae-missing-release-tag) "ExpressionValueSearchContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ExpressionValueSearchContext = ExpressionValueBoxed<'kibana_context', ExecutionContextSearch>; + // Warning: (ae-missing-release-tag) "extractReferences" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) export const extractSearchSourceReferences: (state: SearchSourceFields) => [SearchSourceFields & { indexRefName?: string; -}, SavedObjectReference_2[]]; +}, SavedObjectReference[]]; // Warning: (ae-missing-release-tag) "FieldFormat" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -1338,9 +1367,9 @@ export class IndexPatternsService { // (undocumented) getCache: () => Promise[] | null | undefined>; getDefault: () => Promise; - getFieldsForIndexPattern: (indexPattern: IndexPattern | IndexPatternSpec, options?: GetFieldsOptions) => Promise; + getFieldsForIndexPattern: (indexPattern: IndexPattern | IndexPatternSpec, options?: GetFieldsOptions | undefined) => Promise; // Warning: (ae-forgotten-export) The symbol "GetFieldsOptions" needs to be exported by the entry point index.d.ts - getFieldsForWildcard: (options?: GetFieldsOptions) => Promise; + getFieldsForWildcard: (options: GetFieldsOptions) => Promise; getIds: (refresh?: boolean) => Promise; getIdsWithTitle: (refresh?: boolean) => Promise SearchSourceFields; +}, references: SavedObjectReference[]) => SearchSourceFields; // Warning: (ae-missing-release-tag) "InputTimeRange" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -1510,6 +1539,11 @@ export enum KBN_FIELD_TYPES { UNKNOWN = "unknown" } +// Warning: (ae-missing-release-tag) "KibanaContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type KibanaContext = ExpressionValueSearchContext; + // Warning: (ae-missing-release-tag) "KueryNode" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -1962,8 +1996,8 @@ export const search: { // Warning: (ae-missing-release-tag) "SearchBar" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const SearchBar: React.ComponentClass, "query" | "isLoading" | "filters" | "onRefresh" | "onRefreshChange" | "refreshInterval" | "indexPatterns" | "dataTestSubj" | "timeHistory" | "customSubmitButton" | "screenTitle" | "showQueryBar" | "showQueryInput" | "showFilterBar" | "showDatePicker" | "showAutoRefreshOnly" | "isRefreshPaused" | "dateRangeFrom" | "dateRangeTo" | "showSaveQuery" | "savedQuery" | "onQueryChange" | "onQuerySubmit" | "onSaved" | "onSavedQueryUpdated" | "onClearSavedQuery" | "indicateNoData" | "onFiltersUpdated">, any> & { - WrappedComponent: React.ComponentType & ReactIntl.InjectedIntlProps>; +export const SearchBar: React.ComponentClass, "query" | "isLoading" | "filters" | "onRefresh" | "onRefreshChange" | "refreshInterval" | "indexPatterns" | "dataTestSubj" | "screenTitle" | "showQueryInput" | "showDatePicker" | "showAutoRefreshOnly" | "dateRangeFrom" | "dateRangeTo" | "isRefreshPaused" | "customSubmitButton" | "timeHistory" | "indicateNoData" | "onFiltersUpdated" | "savedQuery" | "showSaveQuery" | "onClearSavedQuery" | "showQueryBar" | "showFilterBar" | "onQueryChange" | "onQuerySubmit" | "onSaved" | "onSavedQueryUpdated">, any> & { + WrappedComponent: React.ComponentType & ReactIntl.InjectedIntlProps>; }; // Warning: (ae-forgotten-export) The symbol "SearchBarOwnProps" needs to be exported by the entry point index.d.ts @@ -2321,21 +2355,21 @@ export const UI_SETTINGS: { // src/plugins/data/public/index.ts:236:27 - (ae-forgotten-export) The symbol "getFromSavedObject" needs to be exported by the entry point index.d.ts // src/plugins/data/public/index.ts:236:27 - (ae-forgotten-export) The symbol "flattenHitWrapper" needs to be exported by the entry point index.d.ts // src/plugins/data/public/index.ts:236:27 - (ae-forgotten-export) The symbol "formatHitProvider" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:387:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:387:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:387:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:387:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:389:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:390:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:399:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:400:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:401:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:402:1 - (ae-forgotten-export) The symbol "isDateHistogramBucketAggConfig" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:406:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:407:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:410:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:411:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:414:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:393:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:393:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:393:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:393:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:395:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:396:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:405:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:406:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:407:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:408:1 - (ae-forgotten-export) The symbol "isDateHistogramBucketAggConfig" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:412:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:413:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:416:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:417:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:420:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts // src/plugins/data/public/query/state_sync/connect_to_query_state.ts:45:5 - (ae-forgotten-export) The symbol "FilterStateStore" needs to be exported by the entry point index.d.ts // (No @packageDocumentation comment for this package) diff --git a/src/plugins/data/public/search/errors/timeout_error.test.tsx b/src/plugins/data/public/search/errors/timeout_error.test.tsx index ad3384c389fbf..2547ee41cbbd7 100644 --- a/src/plugins/data/public/search/errors/timeout_error.test.tsx +++ b/src/plugins/data/public/search/errors/timeout_error.test.tsx @@ -23,7 +23,7 @@ import { coreMock } from '../../../../../core/public/mocks'; const startMock = coreMock.createStart(); import { mount } from 'enzyme'; -import { AbortError } from 'src/plugins/data/common'; +import { AbortError } from '../../../../kibana_utils/public'; describe('SearchTimeoutError', () => { beforeEach(() => { diff --git a/src/plugins/data/public/search/expressions/esdsl.ts b/src/plugins/data/public/search/expressions/esdsl.ts index 2efb21671b5b7..07e904928744f 100644 --- a/src/plugins/data/public/search/expressions/esdsl.ts +++ b/src/plugins/data/public/search/expressions/esdsl.ts @@ -18,15 +18,12 @@ */ import { i18n } from '@kbn/i18n'; -import { - KibanaContext, - ExpressionFunctionDefinition, -} from '../../../../../plugins/expressions/public'; +import { ExpressionFunctionDefinition } from 'src/plugins/expressions/public'; import { getSearchService, getUiSettings } from '../../services'; import { EsRawResponse } from './es_raw_response'; import { RequestStatistics, RequestAdapter } from '../../../../inspector/common'; -import { IEsSearchResponse } from '../../../common/search/es_search'; +import { IEsSearchResponse, KibanaContext } from '../../../common/search'; import { buildEsQuery, getEsQueryConfig } from '../../../common/es_query/es_query'; import { DataPublicPluginStart } from '../../types'; diff --git a/src/plugins/data/public/search/search_interceptor.test.ts b/src/plugins/data/public/search/search_interceptor.test.ts index 472caa5e4f45f..60274261da25f 100644 --- a/src/plugins/data/public/search/search_interceptor.test.ts +++ b/src/plugins/data/public/search/search_interceptor.test.ts @@ -21,7 +21,7 @@ import { CoreSetup, CoreStart } from '../../../../core/public'; import { coreMock } from '../../../../core/public/mocks'; import { IEsSearchRequest } from '../../common/search'; import { SearchInterceptor } from './search_interceptor'; -import { AbortError } from '../../common'; +import { AbortError } from '../../../kibana_utils/public'; import { SearchTimeoutError, PainlessError, TimeoutErrorMode } from './errors'; import { searchServiceMock } from './mocks'; import { ISearchStart } from '.'; diff --git a/src/plugins/data/public/search/search_interceptor.ts b/src/plugins/data/public/search/search_interceptor.ts index 3584d75ab86bb..78e65802bcf99 100644 --- a/src/plugins/data/public/search/search_interceptor.ts +++ b/src/plugins/data/public/search/search_interceptor.ts @@ -24,13 +24,11 @@ import { PublicMethodsOf } from '@kbn/utility-types'; import { CoreStart, CoreSetup, ToastsSetup } from 'kibana/public'; import { i18n } from '@kbn/i18n'; import { - AbortError, IKibanaSearchRequest, IKibanaSearchResponse, ISearchOptions, ES_SEARCH_STRATEGY, ISessionService, - getCombinedSignal, } from '../../common'; import { SearchUsageCollector } from './collectors'; import { @@ -43,6 +41,7 @@ import { getHttpError, } from './errors'; import { toMountPoint } from '../../../kibana_react/public'; +import { AbortError, getCombinedAbortSignal } from '../../../kibana_utils/public'; export interface SearchInterceptorDeps { http: CoreSetup['http']; @@ -170,7 +169,9 @@ export class SearchInterceptor { ...(abortSignal ? [abortSignal] : []), ]; - const { signal: combinedSignal, cleanup: cleanupCombinedSignal } = getCombinedSignal(signals); + const { signal: combinedSignal, cleanup: cleanupCombinedSignal } = getCombinedAbortSignal( + signals + ); const cleanup = () => { subscription.unsubscribe(); combinedSignal.removeEventListener('abort', cleanup); diff --git a/src/plugins/data/public/search/search_service.ts b/src/plugins/data/public/search/search_service.ts index e5a50077518af..96fb3f91ea85f 100644 --- a/src/plugins/data/public/search/search_service.ts +++ b/src/plugins/data/public/search/search_service.ts @@ -23,10 +23,13 @@ import { ISearchSetup, ISearchStart, SearchEnhancements } from './types'; import { handleResponse } from './fetch'; import { + kibana, + kibanaContext, + kibanaContextFunction, ISearchGeneric, - SearchSourceService, - SearchSourceDependencies, ISessionService, + SearchSourceDependencies, + SearchSourceService, } from '../../common/search'; import { getCallMsearch } from './legacy'; import { AggsService, AggsStartDependencies } from './aggs'; @@ -85,6 +88,10 @@ export class SearchService implements Plugin { session: this.sessionService, }); + expressions.registerFunction(kibana); + expressions.registerFunction(kibanaContextFunction); + expressions.registerType(kibanaContext); + expressions.registerFunction(esdsl); expressions.registerType(esRawResponse); diff --git a/src/plugins/data/server/index.ts b/src/plugins/data/server/index.ts index 9a9b8b67730cc..e24869f5237ea 100644 --- a/src/plugins/data/server/index.ts +++ b/src/plugins/data/server/index.ts @@ -134,6 +134,8 @@ export { FieldDescriptor as IndexPatternFieldDescriptor, shouldReadFieldFromDocValues, // used only in logstash_fields fixture FieldDescriptor, + mergeCapabilitiesWithFields, + getCapabilitiesForRollupIndices, } from './index_patterns'; export { @@ -206,6 +208,12 @@ export { OptionedParamType, OptionedValueProp, ParsedInterval, + // expressions + ExecutionContextSearch, + ExpressionFunctionKibana, + ExpressionFunctionKibanaContext, + ExpressionValueSearchContext, + KibanaContext, // search ISearchOptions, IEsSearchRequest, diff --git a/src/plugins/data/server/index_patterns/fetcher/index.ts b/src/plugins/data/server/index_patterns/fetcher/index.ts index 19306696885db..5d8ef62df9627 100644 --- a/src/plugins/data/server/index_patterns/fetcher/index.ts +++ b/src/plugins/data/server/index_patterns/fetcher/index.ts @@ -18,4 +18,8 @@ */ export * from './index_patterns_fetcher'; -export { shouldReadFieldFromDocValues } from './lib'; +export { + shouldReadFieldFromDocValues, + mergeCapabilitiesWithFields, + getCapabilitiesForRollupIndices, +} from './lib'; diff --git a/src/plugins/data/server/index_patterns/fetcher/index_patterns_fetcher.ts b/src/plugins/data/server/index_patterns/fetcher/index_patterns_fetcher.ts index e75b8761984ec..24dad39088b8f 100644 --- a/src/plugins/data/server/index_patterns/fetcher/index_patterns_fetcher.ts +++ b/src/plugins/data/server/index_patterns/fetcher/index_patterns_fetcher.ts @@ -18,8 +18,15 @@ */ import { ElasticsearchClient } from 'kibana/server'; +import { keyBy } from 'lodash'; -import { getFieldCapabilities, resolveTimePattern, createNoMatchingIndicesError } from './lib'; +import { + getFieldCapabilities, + resolveTimePattern, + createNoMatchingIndicesError, + getCapabilitiesForRollupIndices, + mergeCapabilitiesWithFields, +} from './lib'; export interface FieldDescriptor { aggregatable: boolean; @@ -58,11 +65,44 @@ export class IndexPatternsFetcher { pattern: string | string[]; metaFields?: string[]; fieldCapsOptions?: { allow_no_indices: boolean }; + type?: string; + rollupIndex?: string; }): Promise { - const { pattern, metaFields, fieldCapsOptions } = options; - return await getFieldCapabilities(this.elasticsearchClient, pattern, metaFields, { - allow_no_indices: fieldCapsOptions ? fieldCapsOptions.allow_no_indices : this.allowNoIndices, - }); + const { pattern, metaFields, fieldCapsOptions, type, rollupIndex } = options; + const fieldCapsResponse = await getFieldCapabilities( + this.elasticsearchClient, + pattern, + metaFields, + { + allow_no_indices: fieldCapsOptions + ? fieldCapsOptions.allow_no_indices + : this.allowNoIndices, + } + ); + if (type === 'rollup' && rollupIndex) { + const rollupFields: FieldDescriptor[] = []; + const rollupIndexCapabilities = getCapabilitiesForRollupIndices( + ( + await this.elasticsearchClient.rollup.getRollupIndexCaps({ + index: rollupIndex, + }) + ).body + )[rollupIndex].aggs; + const fieldCapsResponseObj = keyBy(fieldCapsResponse, 'name'); + + // Keep meta fields + metaFields!.forEach( + (field: string) => + fieldCapsResponseObj[field] && rollupFields.push(fieldCapsResponseObj[field]) + ); + + return mergeCapabilitiesWithFields( + rollupIndexCapabilities, + fieldCapsResponseObj, + rollupFields + ); + } + return fieldCapsResponse; } /** diff --git a/src/plugins/data/server/index_patterns/fetcher/lib/__tests__/fixtures/index.js b/src/plugins/data/server/index_patterns/fetcher/lib/__tests__/fixtures/index.js new file mode 100644 index 0000000000000..d675702ae54e9 --- /dev/null +++ b/src/plugins/data/server/index_patterns/fetcher/lib/__tests__/fixtures/index.js @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { jobs } from './jobs'; diff --git a/x-pack/plugins/rollup/server/lib/__tests__/fixtures/jobs.js b/src/plugins/data/server/index_patterns/fetcher/lib/__tests__/fixtures/jobs.js similarity index 65% rename from x-pack/plugins/rollup/server/lib/__tests__/fixtures/jobs.js rename to src/plugins/data/server/index_patterns/fetcher/lib/__tests__/fixtures/jobs.js index c03b7c33abe0a..39ebd9595eeaf 100644 --- a/x-pack/plugins/rollup/server/lib/__tests__/fixtures/jobs.js +++ b/src/plugins/data/server/index_patterns/fetcher/lib/__tests__/fixtures/jobs.js @@ -1,7 +1,20 @@ /* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ export const jobs = [ diff --git a/x-pack/plugins/rollup/server/lib/__tests__/jobs_compatibility.js b/src/plugins/data/server/index_patterns/fetcher/lib/__tests__/jobs_compatibility.js similarity index 81% rename from x-pack/plugins/rollup/server/lib/__tests__/jobs_compatibility.js rename to src/plugins/data/server/index_patterns/fetcher/lib/__tests__/jobs_compatibility.js index a67f67de859f5..e3c93ac1f8616 100644 --- a/x-pack/plugins/rollup/server/lib/__tests__/jobs_compatibility.js +++ b/src/plugins/data/server/index_patterns/fetcher/lib/__tests__/jobs_compatibility.js @@ -1,8 +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; - * you may not use this file except in compliance with the Elastic License. + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ + import expect from '@kbn/expect'; import { areJobsCompatible, mergeJobConfigurations } from '../jobs_compatibility'; import { jobs } from './fixtures'; diff --git a/src/plugins/data/server/index_patterns/fetcher/lib/index.ts b/src/plugins/data/server/index_patterns/fetcher/lib/index.ts index 20e74d2b1a579..b2fd3a1a09a25 100644 --- a/src/plugins/data/server/index_patterns/fetcher/lib/index.ts +++ b/src/plugins/data/server/index_patterns/fetcher/lib/index.ts @@ -20,3 +20,5 @@ export { getFieldCapabilities, shouldReadFieldFromDocValues } from './field_capabilities'; export { resolveTimePattern } from './resolve_time_pattern'; export { createNoMatchingIndicesError } from './errors'; +export * from './merge_capabilities_with_fields'; +export * from './map_capabilities'; diff --git a/x-pack/plugins/rollup/server/lib/jobs_compatibility.ts b/src/plugins/data/server/index_patterns/fetcher/lib/jobs_compatibility.ts similarity index 79% rename from x-pack/plugins/rollup/server/lib/jobs_compatibility.ts rename to src/plugins/data/server/index_patterns/fetcher/lib/jobs_compatibility.ts index f5f54cf9a54e8..f21de8907ee24 100644 --- a/x-pack/plugins/rollup/server/lib/jobs_compatibility.ts +++ b/src/plugins/data/server/index_patterns/fetcher/lib/jobs_compatibility.ts @@ -1,7 +1,20 @@ /* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ import { isEqual } from 'lodash'; diff --git a/src/plugins/data/server/index_patterns/fetcher/lib/map_capabilities.ts b/src/plugins/data/server/index_patterns/fetcher/lib/map_capabilities.ts new file mode 100644 index 0000000000000..6187174834012 --- /dev/null +++ b/src/plugins/data/server/index_patterns/fetcher/lib/map_capabilities.ts @@ -0,0 +1,37 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { mergeJobConfigurations } from './jobs_compatibility'; + +export function getCapabilitiesForRollupIndices(indices: { [key: string]: any }) { + const indexNames = Object.keys(indices); + const capabilities = {} as { [key: string]: any }; + + indexNames.forEach((index) => { + try { + capabilities[index] = mergeJobConfigurations(indices[index].rollup_jobs); + } catch (e) { + capabilities[index] = { + error: e.message, + }; + } + }); + + return capabilities; +} diff --git a/x-pack/plugins/rollup/server/lib/merge_capabilities_with_fields.ts b/src/plugins/data/server/index_patterns/fetcher/lib/merge_capabilities_with_fields.ts similarity index 70% rename from x-pack/plugins/rollup/server/lib/merge_capabilities_with_fields.ts rename to src/plugins/data/server/index_patterns/fetcher/lib/merge_capabilities_with_fields.ts index 51111e9e45d0a..dd69f4b7ff007 100644 --- a/x-pack/plugins/rollup/server/lib/merge_capabilities_with_fields.ts +++ b/src/plugins/data/server/index_patterns/fetcher/lib/merge_capabilities_with_fields.ts @@ -1,20 +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; - * you may not use this file except in compliance with the Elastic License. + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ // Merge rollup capabilities information with field information -export interface Field { - name?: string; - [key: string]: any; -} +import { FieldDescriptor } from '../index_patterns_fetcher'; export const mergeCapabilitiesWithFields = ( rollupIndexCapabilities: { [key: string]: any }, fieldsFromFieldCapsApi: { [key: string]: any }, - previousFields: Field[] = [] + previousFields: FieldDescriptor[] = [] ) => { const rollupFields = [...previousFields]; const rollupFieldNames: string[] = []; diff --git a/src/plugins/data/server/index_patterns/index.ts b/src/plugins/data/server/index_patterns/index.ts index 683d1c445fd72..3305b1bb9a92f 100644 --- a/src/plugins/data/server/index_patterns/index.ts +++ b/src/plugins/data/server/index_patterns/index.ts @@ -17,5 +17,11 @@ * under the License. */ export * from './utils'; -export { IndexPatternsFetcher, FieldDescriptor, shouldReadFieldFromDocValues } from './fetcher'; +export { + IndexPatternsFetcher, + FieldDescriptor, + shouldReadFieldFromDocValues, + mergeCapabilitiesWithFields, + getCapabilitiesForRollupIndices, +} from './fetcher'; export { IndexPatternsService, IndexPatternsServiceStart } from './index_patterns_service'; diff --git a/src/plugins/data/server/index_patterns/index_patterns_api_client.ts b/src/plugins/data/server/index_patterns/index_patterns_api_client.ts index 2dc6f40c5a6f1..21a3bf6e73e61 100644 --- a/src/plugins/data/server/index_patterns/index_patterns_api_client.ts +++ b/src/plugins/data/server/index_patterns/index_patterns_api_client.ts @@ -17,13 +17,30 @@ * under the License. */ -import { GetFieldsOptions, IIndexPatternsApiClient } from '../../common/index_patterns/types'; +import { ElasticsearchClient } from 'kibana/server'; +import { + GetFieldsOptions, + IIndexPatternsApiClient, + GetFieldsOptionsTimePattern, +} from '../../common/index_patterns/types'; +import { IndexPatternsFetcher } from './fetcher'; export class IndexPatternsApiServer implements IIndexPatternsApiClient { - async getFieldsForTimePattern(options: GetFieldsOptions = {}) { - throw new Error('IndexPatternsApiServer - getFieldsForTimePattern not defined'); + esClient: ElasticsearchClient; + constructor(elasticsearchClient: ElasticsearchClient) { + this.esClient = elasticsearchClient; } - async getFieldsForWildcard(options: GetFieldsOptions = {}) { - throw new Error('IndexPatternsApiServer - getFieldsForWildcard not defined'); + async getFieldsForWildcard({ pattern, metaFields, type, rollupIndex }: GetFieldsOptions) { + const indexPatterns = new IndexPatternsFetcher(this.esClient); + return await indexPatterns.getFieldsForWildcard({ + pattern, + metaFields, + type, + rollupIndex, + }); + } + async getFieldsForTimePattern(options: GetFieldsOptionsTimePattern) { + const indexPatterns = new IndexPatternsFetcher(this.esClient); + return await indexPatterns.getFieldsForTimePattern(options); } } diff --git a/src/plugins/data/server/index_patterns/index_patterns_service.ts b/src/plugins/data/server/index_patterns/index_patterns_service.ts index d665e3715fa72..af2d4d6a73e0f 100644 --- a/src/plugins/data/server/index_patterns/index_patterns_service.ts +++ b/src/plugins/data/server/index_patterns/index_patterns_service.ts @@ -17,7 +17,14 @@ * under the License. */ -import { CoreSetup, CoreStart, Plugin, Logger, SavedObjectsClientContract } from 'kibana/server'; +import { + CoreSetup, + CoreStart, + Plugin, + Logger, + SavedObjectsClientContract, + ElasticsearchClient, +} from 'kibana/server'; import { registerRoutes } from './routes'; import { indexPatternSavedObjectType } from '../saved_objects'; import { capabilitiesProvider } from './capabilities_provider'; @@ -29,7 +36,8 @@ import { SavedObjectsClientServerToCommon } from './saved_objects_client_wrapper export interface IndexPatternsServiceStart { indexPatternsServiceFactory: ( - savedObjectsClient: SavedObjectsClientContract + savedObjectsClient: SavedObjectsClientContract, + elasticsearchClient: ElasticsearchClient ) => Promise; } @@ -50,14 +58,17 @@ export class IndexPatternsService implements Plugin { + indexPatternsServiceFactory: async ( + savedObjectsClient: SavedObjectsClientContract, + elasticsearchClient: ElasticsearchClient + ) => { const uiSettingsClient = uiSettings.asScopedToClient(savedObjectsClient); const formats = await fieldFormats.fieldFormatServiceFactory(uiSettingsClient); return new IndexPatternsCommonService({ uiSettings: new UiSettingsServerToCommon(uiSettingsClient), savedObjectsClient: new SavedObjectsClientServerToCommon(savedObjectsClient), - apiClient: new IndexPatternsApiServer(), + apiClient: new IndexPatternsApiServer(elasticsearchClient), fieldFormats: formats, onError: (error) => { logger.error(error); diff --git a/src/plugins/data/server/index_patterns/routes.ts b/src/plugins/data/server/index_patterns/routes.ts index 041eb235d01e0..f8af52954fc61 100644 --- a/src/plugins/data/server/index_patterns/routes.ts +++ b/src/plugins/data/server/index_patterns/routes.ts @@ -42,13 +42,15 @@ export function registerRoutes(http: HttpServiceSetup) { meta_fields: schema.oneOf([schema.string(), schema.arrayOf(schema.string())], { defaultValue: [], }), + type: schema.maybe(schema.string()), + rollup_index: schema.maybe(schema.string()), }), }, }, async (context, request, response) => { const { asCurrentUser } = context.core.elasticsearch.client; const indexPatterns = new IndexPatternsFetcher(asCurrentUser); - const { pattern, meta_fields: metaFields } = request.query; + const { pattern, meta_fields: metaFields, type, rollup_index: rollupIndex } = request.query; let parsedFields: string[] = []; try { @@ -61,6 +63,8 @@ export function registerRoutes(http: HttpServiceSetup) { const fields = await indexPatterns.getFieldsForWildcard({ pattern, metaFields: parsedFields, + type, + rollupIndex, }); return response.ok({ diff --git a/src/plugins/data/server/plugin.ts b/src/plugins/data/server/plugin.ts index 88f24b7ca5a70..3ec4e7e64e382 100644 --- a/src/plugins/data/server/plugin.ts +++ b/src/plugins/data/server/plugin.ts @@ -96,7 +96,7 @@ export class DataServerPlugin core.uiSettings.register(getUiSettings()); const searchSetup = this.searchService.setup(core, { - registerFunction: expressions.registerFunction, + expressions, usageCollection, }); diff --git a/src/plugins/data/server/search/aggs/aggs_service.test.ts b/src/plugins/data/server/search/aggs/aggs_service.test.ts index cb4239cc339c4..e58420f6c2f07 100644 --- a/src/plugins/data/server/search/aggs/aggs_service.test.ts +++ b/src/plugins/data/server/search/aggs/aggs_service.test.ts @@ -17,7 +17,7 @@ * under the License. */ -import { KibanaRequest } from 'src/core/server'; +import { KibanaRequest, ElasticsearchClient } from 'src/core/server'; import { coreMock } from '../../../../../core/server/mocks'; import { expressionsPluginMock } from '../../../../../plugins/expressions/server/mocks'; @@ -63,7 +63,8 @@ describe('AggsService - server', () => { expect(start).toHaveProperty('asScopedToClient'); const contract = await start.asScopedToClient( - savedObjects.getScopedClient({} as KibanaRequest) + savedObjects.getScopedClient({} as KibanaRequest), + {} as ElasticsearchClient ); expect(contract).toHaveProperty('calculateAutoTimeExpression'); expect(contract).toHaveProperty('createAggConfigs'); @@ -74,7 +75,10 @@ describe('AggsService - server', () => { service.setup(setupDeps); const start = await service .start(startDeps) - .asScopedToClient(savedObjects.getScopedClient({} as KibanaRequest)); + .asScopedToClient( + savedObjects.getScopedClient({} as KibanaRequest), + {} as ElasticsearchClient + ); expect(start.types.get('terms').name).toBe('terms'); }); @@ -83,7 +87,10 @@ describe('AggsService - server', () => { service.setup(setupDeps); const start = await service .start(startDeps) - .asScopedToClient(savedObjects.getScopedClient({} as KibanaRequest)); + .asScopedToClient( + savedObjects.getScopedClient({} as KibanaRequest), + {} as ElasticsearchClient + ); const aggTypes = getAggTypes(); expect(start.types.getAll().buckets.length).toBe(aggTypes.buckets.length); @@ -103,7 +110,10 @@ describe('AggsService - server', () => { const start = await service .start(startDeps) - .asScopedToClient(savedObjects.getScopedClient({} as KibanaRequest)); + .asScopedToClient( + savedObjects.getScopedClient({} as KibanaRequest), + {} as ElasticsearchClient + ); const aggTypes = getAggTypes(); expect(start.types.getAll().buckets.length).toBe(aggTypes.buckets.length + 1); diff --git a/src/plugins/data/server/search/aggs/aggs_service.ts b/src/plugins/data/server/search/aggs/aggs_service.ts index c805c8af6694c..c23f748b1eeb5 100644 --- a/src/plugins/data/server/search/aggs/aggs_service.ts +++ b/src/plugins/data/server/search/aggs/aggs_service.ts @@ -19,7 +19,11 @@ import { pick } from 'lodash'; -import { UiSettingsServiceStart, SavedObjectsClientContract } from 'src/core/server'; +import { + UiSettingsServiceStart, + SavedObjectsClientContract, + ElasticsearchClient, +} from 'src/core/server'; import { ExpressionsServiceSetup } from 'src/plugins/expressions/common'; import { AggsCommonService, @@ -65,7 +69,10 @@ export class AggsService { public start({ fieldFormats, uiSettings, indexPatterns }: AggsStartDependencies): AggsStart { return { - asScopedToClient: async (savedObjectsClient: SavedObjectsClientContract) => { + asScopedToClient: async ( + savedObjectsClient: SavedObjectsClientContract, + elasticsearchClient: ElasticsearchClient + ) => { const uiSettingsClient = uiSettings.asScopedToClient(savedObjectsClient); const formats = await fieldFormats.fieldFormatServiceFactory(uiSettingsClient); @@ -82,8 +89,9 @@ export class AggsService { types, } = this.aggsCommonService.start({ getConfig, - getIndexPattern: (await indexPatterns.indexPatternsServiceFactory(savedObjectsClient)) - .get, + getIndexPattern: ( + await indexPatterns.indexPatternsServiceFactory(savedObjectsClient, elasticsearchClient) + ).get, isDefaultTimezone, }); diff --git a/src/plugins/data/server/search/aggs/types.ts b/src/plugins/data/server/search/aggs/types.ts index 1b21d948b25d9..2c28c970cbb84 100644 --- a/src/plugins/data/server/search/aggs/types.ts +++ b/src/plugins/data/server/search/aggs/types.ts @@ -17,11 +17,14 @@ * under the License. */ -import { SavedObjectsClientContract } from 'src/core/server'; +import { SavedObjectsClientContract, ElasticsearchClient } from 'src/core/server'; import { AggsCommonSetup, AggsStart as Start } from '../../../common'; export type AggsSetup = AggsCommonSetup; export interface AggsStart { - asScopedToClient: (savedObjectsClient: SavedObjectsClientContract) => Promise; + asScopedToClient: ( + savedObjectsClient: SavedObjectsClientContract, + elasticsearchClient: ElasticsearchClient + ) => Promise; } diff --git a/src/plugins/data/server/search/search_service.test.ts b/src/plugins/data/server/search/search_service.test.ts index 2b513be147e9d..0700afd8d6c83 100644 --- a/src/plugins/data/server/search/search_service.test.ts +++ b/src/plugins/data/server/search/search_service.test.ts @@ -44,7 +44,10 @@ describe('Search service', () => { it('exposes proper contract', async () => { const setup = plugin.setup(mockCoreSetup, ({ packageInfo: { version: '8' }, - registerFunction: jest.fn(), + expressions: { + registerFunction: jest.fn(), + registerType: jest.fn(), + }, } as unknown) as SearchServiceSetupDependencies); expect(setup).toHaveProperty('aggs'); expect(setup).toHaveProperty('registerSearchStrategy'); diff --git a/src/plugins/data/server/search/search_service.ts b/src/plugins/data/server/search/search_service.ts index c500c62914c0b..d8aa588719e3e 100644 --- a/src/plugins/data/server/search/search_service.ts +++ b/src/plugins/data/server/search/search_service.ts @@ -30,6 +30,7 @@ import { StartServicesAccessor, } from 'src/core/server'; import { first } from 'rxjs/operators'; +import { ExpressionsServerSetup } from 'src/plugins/expressions/server'; import { ISearchSetup, ISearchStart, @@ -38,7 +39,7 @@ import { SearchStrategyDependencies, } from './types'; -import { AggsService, AggsSetupDependencies } from './aggs'; +import { AggsService } from './aggs'; import { FieldFormatsStart } from '../field_formats'; import { IndexPatternsServiceStart } from '../index_patterns'; @@ -50,15 +51,18 @@ import { registerUsageCollector } from './collectors/register'; import { usageProvider } from './collectors/usage'; import { searchTelemetry } from '../saved_objects'; import { - IKibanaSearchRequest, - IKibanaSearchResponse, IEsSearchRequest, IEsSearchResponse, + IKibanaSearchRequest, + IKibanaSearchResponse, + ISearchClient, + ISearchOptions, + kibana, + kibanaContext, + kibanaContextFunction, SearchSourceDependencies, - SearchSourceService, searchSourceRequiredUiSettings, - ISearchOptions, - ISearchClient, + SearchSourceService, } from '../../common/search'; import { getShardDelayBucketAgg, @@ -77,7 +81,7 @@ type StrategyMap = Record>; /** @internal */ export interface SearchServiceSetupDependencies { - registerFunction: AggsSetupDependencies['registerFunction']; + expressions: ExpressionsServerSetup; usageCollection?: UsageCollectionSetup; } @@ -106,7 +110,7 @@ export class SearchService implements Plugin { public setup( core: CoreSetup<{}, DataPluginStart>, - { registerFunction, usageCollection }: SearchServiceSetupDependencies + { expressions, usageCollection }: SearchServiceSetupDependencies ): ISearchSetup { const usage = usageCollection ? usageProvider(core) : undefined; @@ -137,7 +141,11 @@ export class SearchService implements Plugin { registerUsageCollector(usageCollection, this.initializerContext); } - const aggs = this.aggsService.setup({ registerFunction }); + expressions.registerFunction(kibana); + expressions.registerFunction(kibanaContextFunction); + expressions.registerType(kibanaContext); + + const aggs = this.aggsService.setup({ registerFunction: expressions.registerFunction }); this.initializerContext.config .create() @@ -146,7 +154,7 @@ export class SearchService implements Plugin { .then((value) => { if (value.search.aggs.shardDelay.enabled) { aggs.types.registerBucket(SHARD_DELAY_AGG_NAME, getShardDelayBucketAgg); - registerFunction(aggShardDelay); + expressions.registerFunction(aggShardDelay); } }); @@ -169,7 +177,11 @@ export class SearchService implements Plugin { const { elasticsearch, savedObjects, uiSettings } = core; const asScoped = this.asScopedProvider(core); return { - aggs: this.aggsService.start({ fieldFormats, uiSettings, indexPatterns }), + aggs: this.aggsService.start({ + fieldFormats, + uiSettings, + indexPatterns, + }), getSearchStrategy: this.getSearchStrategy, asScoped, searchSource: { @@ -177,7 +189,8 @@ export class SearchService implements Plugin { const esClient = elasticsearch.client.asScoped(request); const savedObjectsClient = savedObjects.getScopedClient(request); const scopedIndexPatterns = await indexPatterns.indexPatternsServiceFactory( - savedObjectsClient + savedObjectsClient, + esClient.asCurrentUser ); const uiSettingsClient = uiSettings.asScopedToClient(savedObjectsClient); diff --git a/src/plugins/data/server/server.api.md b/src/plugins/data/server/server.api.md index f62a70c9e4ce1..131b3e4c39c6b 100644 --- a/src/plugins/data/server/server.api.md +++ b/src/plugins/data/server/server.api.md @@ -5,6 +5,7 @@ ```ts import { $Values } from '@kbn/utility-types'; +import { Adapters } from 'src/plugins/inspector/common'; import { ApiResponse } from '@elastic/elasticsearch'; import { Assign } from '@kbn/utility-types'; import { BehaviorSubject } from 'rxjs'; @@ -13,14 +14,19 @@ import { CoreSetup } from 'src/core/server'; import { CoreSetup as CoreSetup_2 } from 'kibana/server'; import { CoreStart } from 'src/core/server'; import { CoreStart as CoreStart_2 } from 'kibana/server'; +import { Datatable } from 'src/plugins/expressions/common'; import { DatatableColumn } from 'src/plugins/expressions'; import { Duration } from 'moment'; -import { ElasticsearchClient } from 'kibana/server'; +import { ElasticsearchClient } from 'src/core/server'; +import { ElasticsearchClient as ElasticsearchClient_2 } from 'kibana/server'; import { Ensure } from '@kbn/utility-types'; import { EnvironmentMode } from '@kbn/config'; import { ErrorToastOptions } from 'src/core/public/notifications'; +import { ExecutionContext } from 'src/plugins/expressions/common'; import { ExpressionAstFunction } from 'src/plugins/expressions/common'; +import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common'; import { ExpressionsServerSetup } from 'src/plugins/expressions/server'; +import { ExpressionValueBoxed } from 'src/plugins/expressions/common'; import { ISavedObjectsRepository } from 'kibana/server'; import { IScopedClusterClient } from 'src/core/server'; import { ISearchOptions as ISearchOptions_2 } from 'src/plugins/data/public'; @@ -55,7 +61,6 @@ import { ToastInputFields } from 'src/core/public/notifications'; import { Type } from '@kbn/config-schema'; import { TypeOf } from '@kbn/config-schema'; import { Unit } from '@elastic/datemath'; -import { UnwrapPromiseOrReturn } from '@kbn/utility-types'; // Warning: (ae-forgotten-export) The symbol "AggConfigSerialized" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "AggConfigOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) @@ -224,7 +229,6 @@ export enum ES_FIELD_TYPES { // @public (undocumented) export const ES_SEARCH_STRATEGY = "es"; -// Warning: (ae-forgotten-export) The symbol "ExpressionFunctionDefinition" needs to be exported by the entry point index.d.ts // Warning: (ae-forgotten-export) The symbol "Input" needs to be exported by the entry point index.d.ts // Warning: (ae-forgotten-export) The symbol "Arguments" needs to be exported by the entry point index.d.ts // Warning: (ae-forgotten-export) The symbol "Output" needs to be exported by the entry point index.d.ts @@ -285,6 +289,31 @@ export interface EsQueryConfig { queryStringOptions: Record; } +// Warning: (ae-missing-release-tag) "ExecutionContextSearch" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ExecutionContextSearch = { + filters?: Filter[]; + query?: Query | Query[]; + timeRange?: TimeRange; +}; + +// Warning: (ae-missing-release-tag) "ExpressionFunctionKibana" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ExpressionFunctionKibana = ExpressionFunctionDefinition<'kibana', ExpressionValueSearchContext | null, object, ExpressionValueSearchContext, ExecutionContext>; + +// Warning: (ae-forgotten-export) The symbol "Arguments" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "ExpressionFunctionKibanaContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ExpressionFunctionKibanaContext = ExpressionFunctionDefinition<'kibana_context', KibanaContext | null, Arguments_2, Promise, ExecutionContext>; + +// Warning: (ae-missing-release-tag) "ExpressionValueSearchContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ExpressionValueSearchContext = ExpressionValueBoxed<'kibana_context', ExecutionContextSearch>; + // Warning: (ae-missing-release-tag) "FieldDescriptor" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -361,6 +390,15 @@ export type Filter = { query?: any; }; +// Warning: (ae-missing-release-tag) "getCapabilitiesForRollupIndices" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export function getCapabilitiesForRollupIndices(indices: { + [key: string]: any; +}): { + [key: string]: any; +}; + // Warning: (ae-forgotten-export) The symbol "IUiSettingsClient" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "getDefaultSearchParams" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -660,7 +698,7 @@ export const indexPatterns: { // // @public (undocumented) export class IndexPatternsFetcher { - constructor(elasticsearchClient: ElasticsearchClient, allowNoIndices?: boolean); + constructor(elasticsearchClient: ElasticsearchClient_2, allowNoIndices?: boolean); getFieldsForTimePattern(options: { pattern: string; metaFields: string[]; @@ -673,6 +711,8 @@ export class IndexPatternsFetcher { fieldCapsOptions?: { allow_no_indices: boolean; }; + type?: string; + rollupIndex?: string; }): Promise; } @@ -687,7 +727,7 @@ export class IndexPatternsService implements Plugin_3 Promise; + indexPatternsServiceFactory: (savedObjectsClient: SavedObjectsClientContract_2, elasticsearchClient: ElasticsearchClient_2) => Promise; }; } @@ -779,6 +819,11 @@ export enum KBN_FIELD_TYPES { UNKNOWN = "unknown" } +// Warning: (ae-missing-release-tag) "KibanaContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type KibanaContext = ExpressionValueSearchContext; + // Warning: (ae-missing-release-tag) "KueryNode" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -791,6 +836,15 @@ export interface KueryNode { type: keyof NodeTypes; } +// Warning: (ae-missing-release-tag) "mergeCapabilitiesWithFields" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const mergeCapabilitiesWithFields: (rollupIndexCapabilities: { + [key: string]: any; +}, fieldsFromFieldCapsApi: { + [key: string]: any; +}, previousFields?: FieldDescriptor[]) => FieldDescriptor[]; + // Warning: (ae-missing-release-tag) "METRIC_TYPES" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -885,7 +939,7 @@ export class Plugin implements Plugin_2 void; search: ISearchSetup; fieldFormats: { - register: (customFieldFormat: import("../public").FieldFormatInstanceType) => number; + register: (customFieldFormat: import("../common").FieldFormatInstanceType) => number; }; }; // (undocumented) @@ -894,7 +948,7 @@ export class Plugin implements Plugin_2 Promise; }; indexPatterns: { - indexPatternsServiceFactory: (savedObjectsClient: Pick) => Promise; + indexPatternsServiceFactory: (savedObjectsClient: Pick, elasticsearchClient: import("src/core/server").ElasticsearchClient) => Promise; }; search: ISearchStart>; }; @@ -1162,22 +1216,22 @@ export function usageProvider(core: CoreSetup_2): SearchUsage; // src/plugins/data/server/index.ts:101:26 - (ae-forgotten-export) The symbol "TruncateFormat" needs to be exported by the entry point index.d.ts // src/plugins/data/server/index.ts:127:27 - (ae-forgotten-export) The symbol "isFilterable" needs to be exported by the entry point index.d.ts // src/plugins/data/server/index.ts:127:27 - (ae-forgotten-export) The symbol "isNestedField" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:235:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:235:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:235:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:235:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:250:5 - (ae-forgotten-export) The symbol "getTotalLoaded" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:251:5 - (ae-forgotten-export) The symbol "toSnakeCase" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:255:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:256:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:265:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:266:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:267:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:271:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:272:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:276:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:279:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index_patterns/index_patterns_service.ts:50:14 - (ae-forgotten-export) The symbol "IndexPatternsService" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:243:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:243:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:243:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:243:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:258:5 - (ae-forgotten-export) The symbol "getTotalLoaded" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:259:5 - (ae-forgotten-export) The symbol "toSnakeCase" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:263:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:264:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:273:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:274:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:275:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:279:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:280:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:284:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:287:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index_patterns/index_patterns_service.ts:58:14 - (ae-forgotten-export) The symbol "IndexPatternsService" needs to be exported by the entry point index.d.ts // src/plugins/data/server/plugin.ts:88:66 - (ae-forgotten-export) The symbol "DataEnhancements" needs to be exported by the entry point index.d.ts // src/plugins/data/server/search/types.ts:104:5 - (ae-forgotten-export) The symbol "ISearchStartSearchSource" needs to be exported by the entry point index.d.ts diff --git a/src/plugins/es_ui_shared/public/url/attempt_to_uri_decode.test.ts b/src/plugins/es_ui_shared/public/url/attempt_to_uri_decode.test.ts index 15750c7667800..6654611faa18b 100644 --- a/src/plugins/es_ui_shared/public/url/attempt_to_uri_decode.test.ts +++ b/src/plugins/es_ui_shared/public/url/attempt_to_uri_decode.test.ts @@ -19,14 +19,51 @@ import { attemptToURIDecode } from './attempt_to_uri_decode'; +// this function doesn't work for % with other special chars or sequence %25 +// known issue https://github.com/elastic/kibana/issues/82440 test('decodes an encoded string', () => { - const encodedString = 'test%3F'; - expect(attemptToURIDecode(encodedString)).toBe('test?'); + const originalName = 'test;,/?:@&=+$#'; + const encodedName = encodeURIComponent(originalName); + // react router v5 automatically decodes route match params + const reactRouterDecoded = decodeURI(encodedName); + + expect(attemptToURIDecode(encodedName)).toBe(originalName); + expect(attemptToURIDecode(reactRouterDecoded)).toBe(originalName); }); -// react router partially decodes %25 sequence to % in match params -// https://github.com/elastic/kibana/pull/81664 test('ignores the error if a string is already decoded', () => { - const decodedString = 'test%'; - expect(attemptToURIDecode(decodedString)).toBe(decodedString); + const originalName = 'test%'; + + const encodedName = encodeURIComponent(originalName); + // react router v5 automatically decodes route match params + const reactRouterDecoded = decodeURI(encodedName); + + expect(attemptToURIDecode(encodedName)).toBe(originalName); + expect(attemptToURIDecode(reactRouterDecoded)).toBe(originalName); +}); + +test('returns wrong decoded value for %25 sequence', () => { + const originalName = 'test%25'; + + const encodedName = encodeURIComponent(originalName); + // react router v5 automatically decodes route match params + const reactRouterDecoded = decodeURI(encodedName); + + expect(attemptToURIDecode(encodedName)).toBe(originalName); + expect(attemptToURIDecode(reactRouterDecoded)).not.toBe(originalName); +}); + +test('returns wrong decoded value for % with other escaped characters', () => { + const originalName = 'test%?#'; + + const encodedName = encodeURIComponent(originalName); + // react router v5 automatically decodes route match params + const reactRouterDecoded = decodeURI(encodedName); + + expect(attemptToURIDecode(encodedName)).toBe(originalName); + expect(attemptToURIDecode(reactRouterDecoded)).not.toBe(originalName); +}); + +test("doesn't convert undefined to a string", () => { + expect(attemptToURIDecode(undefined)).toBeUndefined(); }); diff --git a/src/plugins/es_ui_shared/public/url/attempt_to_uri_decode.ts b/src/plugins/es_ui_shared/public/url/attempt_to_uri_decode.ts index 65444b83f77bb..37e4761106e44 100644 --- a/src/plugins/es_ui_shared/public/url/attempt_to_uri_decode.ts +++ b/src/plugins/es_ui_shared/public/url/attempt_to_uri_decode.ts @@ -19,12 +19,14 @@ /* * Use this function with any match params coming from react router to safely decode values. - * https://github.com/elastic/kibana/pull/81664 + * After an update to react router v6, this functions should be deprecated. + * Known issue for navigation with special characters in paths + * https://github.com/elastic/kibana/issues/82440 */ -export const attemptToURIDecode = (value: string) => { +export const attemptToURIDecode = (value?: string): string | undefined => { let result = value; try { - result = decodeURIComponent(value); + result = value ? decodeURIComponent(value) : value; } catch (e) { // do nothing } diff --git a/src/plugins/expressions/common/execution/execution.ts b/src/plugins/expressions/common/execution/execution.ts index ba115a7538604..50a469c338d73 100644 --- a/src/plugins/expressions/common/execution/execution.ts +++ b/src/plugins/expressions/common/execution/execution.ts @@ -22,8 +22,7 @@ import { keys, last, mapValues, reduce, zipObject } from 'lodash'; import { Executor } from '../executor'; import { createExecutionContainer, ExecutionContainer } from './container'; import { createError } from '../util'; -import { Defer, now } from '../../../kibana_utils/common'; -import { toPromise } from '../../../data/common/utils/abort_utils'; +import { abortSignalToPromise, Defer, now } from '../../../kibana_utils/common'; import { RequestAdapter, DataAdapter, Adapters } from '../../../inspector/common'; import { isExpressionValueError, ExpressionValueError } from '../expression_types/specs/error'; import { @@ -93,7 +92,7 @@ export class Execution< /** * Promise that rejects if/when abort controller sends "abort" signal. */ - private readonly abortRejection = toPromise(this.abortController.signal); + private readonly abortRejection = abortSignalToPromise(this.abortController.signal); /** * Races a given promise against the "abort" event of `abortController`. diff --git a/src/plugins/expressions/common/execution/types.ts b/src/plugins/expressions/common/execution/types.ts index 50475c3bd94ae..abe3e08fc20c2 100644 --- a/src/plugins/expressions/common/execution/types.ts +++ b/src/plugins/expressions/common/execution/types.ts @@ -17,16 +17,18 @@ * under the License. */ -import { ExpressionType } from '../expression_types'; +import { ExpressionType, SerializableState } from '../expression_types'; import { Adapters, DataAdapter, RequestAdapter } from '../../../inspector/common'; -import { TimeRange, Query, Filter } from '../../../data/common'; import { SavedObject, SavedObjectAttributes } from '../../../../core/public'; /** * `ExecutionContext` is an object available to all functions during a single execution; * it provides various methods to perform side-effects. */ -export interface ExecutionContext { +export interface ExecutionContext< + InspectorAdapters extends Adapters = Adapters, + ExecutionContextSearch extends SerializableState = SerializableState +> { /** * Get search context of the expression. */ @@ -79,9 +81,3 @@ export interface DefaultInspectorAdapters extends Adapters { requests: RequestAdapter; data: DataAdapter; } - -export interface ExecutionContextSearch { - filters?: Filter[]; - query?: Query | Query[]; - timeRange?: TimeRange; -} diff --git a/src/plugins/expressions/common/expression_functions/specs/index.ts b/src/plugins/expressions/common/expression_functions/specs/index.ts index 11706f65dbd32..10ccd014fd7bd 100644 --- a/src/plugins/expressions/common/expression_functions/specs/index.ts +++ b/src/plugins/expressions/common/expression_functions/specs/index.ts @@ -19,8 +19,6 @@ import { clog } from './clog'; import { font } from './font'; -import { kibana } from './kibana'; -import { kibanaContextFunction } from './kibana_context'; import { variableSet } from './var_set'; import { variable } from './var'; import { AnyExpressionFunctionDefinition } from '../types'; @@ -32,8 +30,6 @@ import { movingAverage } from './moving_average'; export const functionSpecs: AnyExpressionFunctionDefinition[] = [ clog, font, - kibana, - kibanaContextFunction, variableSet, variable, theme, @@ -44,8 +40,6 @@ export const functionSpecs: AnyExpressionFunctionDefinition[] = [ export * from './clog'; export * from './font'; -export * from './kibana'; -export * from './kibana_context'; export * from './var_set'; export * from './var'; export * from './theme'; diff --git a/src/plugins/expressions/common/expression_functions/specs/tests/var.test.ts b/src/plugins/expressions/common/expression_functions/specs/tests/var.test.ts index 762f34e3f5566..efcb5555cc63b 100644 --- a/src/plugins/expressions/common/expression_functions/specs/tests/var.test.ts +++ b/src/plugins/expressions/common/expression_functions/specs/tests/var.test.ts @@ -20,12 +20,11 @@ import { functionWrapper } from './utils'; import { variable } from '../var'; import { ExecutionContext } from '../../../execution/types'; -import { KibanaContext } from '../../../expression_types'; describe('expression_functions', () => { describe('var', () => { const fn = functionWrapper(variable); - let input: Partial; + let input: Partial>; let context: ExecutionContext; beforeEach(() => { diff --git a/src/plugins/expressions/common/expression_functions/specs/tests/var_set.test.ts b/src/plugins/expressions/common/expression_functions/specs/tests/var_set.test.ts index 365ae5b89baea..17d9c4ab98c1a 100644 --- a/src/plugins/expressions/common/expression_functions/specs/tests/var_set.test.ts +++ b/src/plugins/expressions/common/expression_functions/specs/tests/var_set.test.ts @@ -20,12 +20,11 @@ import { functionWrapper } from './utils'; import { variableSet } from '../var_set'; import { ExecutionContext } from '../../../execution/types'; -import { KibanaContext } from '../../../expression_types'; describe('expression_functions', () => { describe('var_set', () => { const fn = functionWrapper(variableSet); - let input: Partial; + let input: Partial>; let context: ExecutionContext; let variables: Record; diff --git a/src/plugins/expressions/common/expression_functions/types.ts b/src/plugins/expressions/common/expression_functions/types.ts index 4a93cfa9211ff..52e4b4d9facf3 100644 --- a/src/plugins/expressions/common/expression_functions/types.ts +++ b/src/plugins/expressions/common/expression_functions/types.ts @@ -24,8 +24,6 @@ import { ExecutionContext } from '../execution/types'; import { ExpressionFunctionClog, ExpressionFunctionFont, - ExpressionFunctionKibanaContext, - ExpressionFunctionKibana, ExpressionFunctionVarSet, ExpressionFunctionVar, ExpressionFunctionTheme, @@ -129,8 +127,6 @@ export type AnyExpressionFunctionDefinition = ExpressionFunctionDefinition< export interface ExpressionFunctionDefinitions { clog: ExpressionFunctionClog; font: ExpressionFunctionFont; - kibana_context: ExpressionFunctionKibanaContext; - kibana: ExpressionFunctionKibana; var_set: ExpressionFunctionVarSet; var: ExpressionFunctionVar; theme: ExpressionFunctionTheme; diff --git a/src/plugins/expressions/common/expression_types/specs/index.ts b/src/plugins/expressions/common/expression_types/specs/index.ts index 00c52a2545cd6..ec8dee1f7fc52 100644 --- a/src/plugins/expressions/common/expression_types/specs/index.ts +++ b/src/plugins/expressions/common/expression_types/specs/index.ts @@ -22,7 +22,6 @@ import { datatable } from './datatable'; import { error } from './error'; import { filter } from './filter'; import { image } from './image'; -import { kibanaContext } from './kibana_context'; import { nullType } from './null'; import { num } from './num'; import { number } from './number'; @@ -40,7 +39,6 @@ export const typeSpecs: AnyExpressionTypeDefinition[] = [ error, filter, image, - kibanaContext, nullType, num, number, @@ -57,7 +55,6 @@ export * from './datatable'; export * from './error'; export * from './filter'; export * from './image'; -export * from './kibana_context'; export * from './null'; export * from './num'; export * from './number'; diff --git a/src/plugins/expressions/common/service/expressions_services.ts b/src/plugins/expressions/common/service/expressions_services.ts index 01289ca1ae57a..c9cc0680360bb 100644 --- a/src/plugins/expressions/common/service/expressions_services.ts +++ b/src/plugins/expressions/common/service/expressions_services.ts @@ -26,7 +26,6 @@ import { AnyExpressionFunctionDefinition } from '../expression_functions'; import { SavedObjectReference } from '../../../../core/types'; import { PersistableStateService, SerializableState } from '../../../kibana_utils/common'; import { Adapters } from '../../../inspector/common/adapters'; -import { ExecutionContextSearch } from '../execution'; /** * The public contract that `ExpressionsService` provides to other plugins @@ -48,7 +47,7 @@ export type ExpressionsServiceSetup = Pick< >; export interface ExpressionExecutionParams { - searchContext?: ExecutionContextSearch; + searchContext?: SerializableState; variables?: Record; diff --git a/src/plugins/expressions/kibana.json b/src/plugins/expressions/kibana.json index 67bbf4b6e5454..23c7fe722fdb3 100644 --- a/src/plugins/expressions/kibana.json +++ b/src/plugins/expressions/kibana.json @@ -6,7 +6,6 @@ "extraPublicDirs": ["common", "common/fonts"], "requiredBundles": [ "kibanaUtils", - "inspector", - "data" + "inspector" ] } diff --git a/src/plugins/expressions/public/index.ts b/src/plugins/expressions/public/index.ts index 893d68238747d..385055bc2fdc2 100644 --- a/src/plugins/expressions/public/index.ts +++ b/src/plugins/expressions/public/index.ts @@ -66,7 +66,6 @@ export { ExpressionFunction, ExpressionFunctionDefinition, ExpressionFunctionDefinitions, - ExpressionFunctionKibana, ExpressionFunctionParameter, ExpressionImage, ExpressionRenderDefinition, @@ -81,7 +80,6 @@ export { ExpressionValueError, ExpressionValueNum, ExpressionValueRender, - ExpressionValueSearchContext, ExpressionValueUnboxed, ExpressionValueFilter, Font, @@ -96,8 +94,6 @@ export { InterpreterErrorType, IRegistry, isExpressionAstBuilder, - KIBANA_CONTEXT_NAME, - KibanaContext, KnownTypeToString, Overflow, parse, diff --git a/src/plugins/expressions/public/plugin.test.ts b/src/plugins/expressions/public/plugin.test.ts index d9dde1f6def68..0b21fe354d3d3 100644 --- a/src/plugins/expressions/public/plugin.test.ts +++ b/src/plugins/expressions/public/plugin.test.ts @@ -50,14 +50,6 @@ describe('ExpressionsPublicPlugin', () => { const bar = await setup.run('var_set name="foo" value="bar" | var name="foo"', null); expect(bar).toBe('bar'); }); - - test('kibana_context function is available', async () => { - const { setup } = await expressionsPluginMock.createPlugin(); - const result = await setup.run('kibana_context', null); - expect(result).toMatchObject({ - type: 'kibana_context', - }); - }); }); }); @@ -81,15 +73,6 @@ describe('ExpressionsPublicPlugin', () => { } `); }); - - test('"kibana" function return value of type "kibana_context"', async () => { - const { doStart } = await expressionsPluginMock.createPlugin(); - const start = await doStart(); - const execution = start.execute('kibana', null); - const result = await execution.getData(); - - expect((result as any).type).toBe('kibana_context'); - }); }); }); }); diff --git a/src/plugins/expressions/public/public.api.md b/src/plugins/expressions/public/public.api.md index 773d61ebe2e28..17f8e6255f6bb 100644 --- a/src/plugins/expressions/public/public.api.md +++ b/src/plugins/expressions/public/public.api.md @@ -130,15 +130,15 @@ export class Execution = StateContainer, ExecutionPureTransitions>; +// Warning: (ae-forgotten-export) The symbol "SerializableState" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "ExecutionContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public -export interface ExecutionContext { +export interface ExecutionContext { abortSignal: AbortSignal; // Warning: (ae-forgotten-export) The symbol "SavedObjectAttributes" needs to be exported by the entry point index.d.ts // Warning: (ae-forgotten-export) The symbol "SavedObject" needs to be exported by the entry point index.d.ts getSavedObject?: (type: string, id: string) => Promise>; - // Warning: (ae-forgotten-export) The symbol "ExecutionContextSearch" needs to be exported by the entry point index.d.ts getSearchContext: () => ExecutionContextSearch; getSearchSessionId: () => string | undefined; inspectorAdapters: InspectorAdapters; @@ -396,12 +396,6 @@ export interface ExpressionFunctionDefinitions { // // (undocumented) font: ExpressionFunctionFont; - // (undocumented) - kibana: ExpressionFunctionKibana; - // Warning: (ae-forgotten-export) The symbol "ExpressionFunctionKibanaContext" needs to be exported by the entry point index.d.ts - // - // (undocumented) - kibana_context: ExpressionFunctionKibanaContext; // Warning: (ae-forgotten-export) The symbol "ExpressionFunctionMovingAverage" needs to be exported by the entry point index.d.ts // // (undocumented) @@ -420,11 +414,6 @@ export interface ExpressionFunctionDefinitions { var_set: ExpressionFunctionVarSet; } -// Warning: (ae-missing-release-tag) "ExpressionFunctionKibana" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export type ExpressionFunctionKibana = ExpressionFunctionDefinition<'kibana', ExpressionValueSearchContext | null, object, ExpressionValueSearchContext>; - // Warning: (ae-missing-release-tag) "ExpressionFunctionParameter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -789,11 +778,6 @@ export { ExpressionValueRender } export { ExpressionValueRender as Render } -// Warning: (ae-missing-release-tag) "ExpressionValueSearchContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export type ExpressionValueSearchContext = ExpressionValueBoxed<'kibana_context', ExecutionContextSearch>; - // Warning: (ae-missing-release-tag) "ExpressionValueUnboxed" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -908,7 +892,7 @@ export interface IExpressionLoaderParams { // (undocumented) onRenderError?: RenderErrorHandlerFnType; // (undocumented) - searchContext?: ExecutionContextSearch; + searchContext?: SerializableState_2; // (undocumented) searchSessionId?: string; // (undocumented) @@ -956,16 +940,6 @@ export interface IRegistry { // @public export function isExpressionAstBuilder(val: any): val is ExpressionAstExpressionBuilder; -// Warning: (ae-missing-release-tag) "KIBANA_CONTEXT_NAME" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export type KIBANA_CONTEXT_NAME = 'kibana_context'; - -// Warning: (ae-missing-release-tag) "KibanaContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export type KibanaContext = ExpressionValueSearchContext; - // Warning: (ae-missing-release-tag) "KnownTypeToString" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public diff --git a/src/plugins/expressions/public/types/index.ts b/src/plugins/expressions/public/types/index.ts index 1643b5734ef1a..4af36fea169a1 100644 --- a/src/plugins/expressions/public/types/index.ts +++ b/src/plugins/expressions/public/types/index.ts @@ -21,8 +21,8 @@ import { Adapters } from '../../../inspector/public'; import { IInterpreterRenderHandlers, ExpressionValue, - ExecutionContextSearch, ExpressionsService, + SerializableState, } from '../../common'; /** @@ -42,7 +42,7 @@ export interface ExpressionInterpreter { } export interface IExpressionLoaderParams { - searchContext?: ExecutionContextSearch; + searchContext?: SerializableState; context?: ExpressionValue; variables?: Record; // Enables debug tracking on each expression in the AST diff --git a/src/plugins/expressions/server/index.ts b/src/plugins/expressions/server/index.ts index cc22d4b500d97..287b91049b1ae 100644 --- a/src/plugins/expressions/server/index.ts +++ b/src/plugins/expressions/server/index.ts @@ -57,7 +57,6 @@ export { ExpressionFunction, ExpressionFunctionDefinition, ExpressionFunctionDefinitions, - ExpressionFunctionKibana, ExpressionFunctionParameter, ExpressionImage, ExpressionRenderDefinition, @@ -72,7 +71,6 @@ export { ExpressionValueError, ExpressionValueNum, ExpressionValueRender, - ExpressionValueSearchContext, ExpressionValueUnboxed, ExpressionValueFilter, Font, @@ -87,8 +85,6 @@ export { InterpreterErrorType, IRegistry, isExpressionAstBuilder, - KIBANA_CONTEXT_NAME, - KibanaContext, KnownTypeToString, Overflow, parse, diff --git a/src/plugins/expressions/server/server.api.md b/src/plugins/expressions/server/server.api.md index 27a3193bf7894..e5b499206ebdd 100644 --- a/src/plugins/expressions/server/server.api.md +++ b/src/plugins/expressions/server/server.api.md @@ -128,15 +128,15 @@ export class Execution = StateContainer, ExecutionPureTransitions>; +// Warning: (ae-forgotten-export) The symbol "SerializableState" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "ExecutionContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public -export interface ExecutionContext { +export interface ExecutionContext { abortSignal: AbortSignal; // Warning: (ae-forgotten-export) The symbol "SavedObjectAttributes" needs to be exported by the entry point index.d.ts // Warning: (ae-forgotten-export) The symbol "SavedObject" needs to be exported by the entry point index.d.ts getSavedObject?: (type: string, id: string) => Promise>; - // Warning: (ae-forgotten-export) The symbol "ExecutionContextSearch" needs to be exported by the entry point index.d.ts getSearchContext: () => ExecutionContextSearch; getSearchSessionId: () => string | undefined; inspectorAdapters: InspectorAdapters; @@ -368,12 +368,6 @@ export interface ExpressionFunctionDefinitions { // // (undocumented) font: ExpressionFunctionFont; - // (undocumented) - kibana: ExpressionFunctionKibana; - // Warning: (ae-forgotten-export) The symbol "ExpressionFunctionKibanaContext" needs to be exported by the entry point index.d.ts - // - // (undocumented) - kibana_context: ExpressionFunctionKibanaContext; // Warning: (ae-forgotten-export) The symbol "ExpressionFunctionMovingAverage" needs to be exported by the entry point index.d.ts // // (undocumented) @@ -392,11 +386,6 @@ export interface ExpressionFunctionDefinitions { var_set: ExpressionFunctionVarSet; } -// Warning: (ae-missing-release-tag) "ExpressionFunctionKibana" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export type ExpressionFunctionKibana = ExpressionFunctionDefinition<'kibana', ExpressionValueSearchContext | null, object, ExpressionValueSearchContext>; - // Warning: (ae-missing-release-tag) "ExpressionFunctionParameter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -640,11 +629,6 @@ export { ExpressionValueRender } export { ExpressionValueRender as Render } -// Warning: (ae-missing-release-tag) "ExpressionValueSearchContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export type ExpressionValueSearchContext = ExpressionValueBoxed<'kibana_context', ExecutionContextSearch>; - // Warning: (ae-missing-release-tag) "ExpressionValueUnboxed" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -777,16 +761,6 @@ export interface IRegistry { // @public export function isExpressionAstBuilder(val: any): val is ExpressionAstExpressionBuilder; -// Warning: (ae-missing-release-tag) "KIBANA_CONTEXT_NAME" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export type KIBANA_CONTEXT_NAME = 'kibana_context'; - -// Warning: (ae-missing-release-tag) "KibanaContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export type KibanaContext = ExpressionValueSearchContext; - // Warning: (ae-missing-release-tag) "KnownTypeToString" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public diff --git a/src/plugins/data/common/utils/abort_utils.test.ts b/src/plugins/kibana_utils/common/abort_utils.test.ts similarity index 84% rename from src/plugins/data/common/utils/abort_utils.test.ts rename to src/plugins/kibana_utils/common/abort_utils.test.ts index 358f00e5e82bd..8ccbf752b4d1b 100644 --- a/src/plugins/data/common/utils/abort_utils.test.ts +++ b/src/plugins/kibana_utils/common/abort_utils.test.ts @@ -17,7 +17,7 @@ * under the License. */ -import { AbortError, toPromise, getCombinedSignal } from './abort_utils'; +import { AbortError, abortSignalToPromise, getCombinedAbortSignal } from './abort_utils'; jest.useFakeTimers(); @@ -37,11 +37,11 @@ describe('AbortUtils', () => { }); }); - describe('toPromise', () => { + describe('abortSignalToPromise', () => { describe('rejects', () => { test('should not reject if the signal does not abort', async () => { const controller = new AbortController(); - const promise = toPromise(controller.signal).promise; + const promise = abortSignalToPromise(controller.signal).promise; const whenRejected = jest.fn(); promise.catch(whenRejected); await flushPromises(); @@ -50,7 +50,7 @@ describe('AbortUtils', () => { test('should reject if the signal does abort', async () => { const controller = new AbortController(); - const promise = toPromise(controller.signal).promise; + const promise = abortSignalToPromise(controller.signal).promise; const whenRejected = jest.fn(); promise.catch(whenRejected); controller.abort(); @@ -61,13 +61,13 @@ describe('AbortUtils', () => { test('should expose cleanup handler', () => { const controller = new AbortController(); - const promise = toPromise(controller.signal); + const promise = abortSignalToPromise(controller.signal); expect(promise.cleanup).toBeDefined(); }); test('calling clean up handler prevents rejects', async () => { const controller = new AbortController(); - const { promise, cleanup } = toPromise(controller.signal); + const { promise, cleanup } = abortSignalToPromise(controller.signal); const whenRejected = jest.fn(); promise.catch(whenRejected); cleanup(); @@ -78,9 +78,9 @@ describe('AbortUtils', () => { }); }); - describe('getCombinedSignal', () => { + describe('getCombinedAbortSignal', () => { test('should return an AbortSignal', () => { - const signal = getCombinedSignal([]).signal; + const signal = getCombinedAbortSignal([]).signal; expect(signal).toBeInstanceOf(AbortSignal); }); @@ -89,7 +89,7 @@ describe('AbortUtils', () => { const controller2 = new AbortController(); setTimeout(() => controller1.abort(), 2000); setTimeout(() => controller2.abort(), 1000); - const signal = getCombinedSignal([controller1.signal, controller2.signal]).signal; + const signal = getCombinedAbortSignal([controller1.signal, controller2.signal]).signal; expect(signal.aborted).toBe(false); jest.advanceTimersByTime(500); await flushPromises(); @@ -101,7 +101,7 @@ describe('AbortUtils', () => { const controller2 = new AbortController(); setTimeout(() => controller1.abort(), 2000); setTimeout(() => controller2.abort(), 1000); - const signal = getCombinedSignal([controller1.signal, controller2.signal]).signal; + const signal = getCombinedAbortSignal([controller1.signal, controller2.signal]).signal; expect(signal.aborted).toBe(false); jest.advanceTimersByTime(1000); await flushPromises(); @@ -112,7 +112,7 @@ describe('AbortUtils', () => { const controller1 = new AbortController(); const controller2 = new AbortController(); controller1.abort(); - const signal = getCombinedSignal([controller1.signal, controller2.signal]).signal; + const signal = getCombinedAbortSignal([controller1.signal, controller2.signal]).signal; expect(signal.aborted).toBe(true); }); @@ -132,7 +132,7 @@ describe('AbortUtils', () => { const controller1 = createMockController(); const controller2 = createMockController(); - const { cleanup } = getCombinedSignal([ + const { cleanup } = getCombinedAbortSignal([ controller1.controller.signal, controller2.controller.signal, ]); @@ -150,7 +150,7 @@ describe('AbortUtils', () => { const controller1 = createMockController(); const controller2 = createMockController(); - getCombinedSignal([controller1.controller.signal, controller2.controller.signal]); + getCombinedAbortSignal([controller1.controller.signal, controller2.controller.signal]); expect(controller1.getTotalListeners()).toBe(1); expect(controller2.getTotalListeners()).toBe(1); diff --git a/src/plugins/data/common/utils/abort_utils.ts b/src/plugins/kibana_utils/common/abort_utils.ts similarity index 91% rename from src/plugins/data/common/utils/abort_utils.ts rename to src/plugins/kibana_utils/common/abort_utils.ts index 81f30b7454c7b..dd8db34931693 100644 --- a/src/plugins/data/common/utils/abort_utils.ts +++ b/src/plugins/kibana_utils/common/abort_utils.ts @@ -36,7 +36,9 @@ export class AbortError extends Error { * * @param signal The `AbortSignal` to generate the `Promise` from */ -export function toPromise(signal: AbortSignal): { promise: Promise; cleanup: () => void } { +export function abortSignalToPromise( + signal: AbortSignal +): { promise: Promise; cleanup: () => void } { let abortHandler: () => void; const cleanup = () => { if (abortHandler) { @@ -60,7 +62,7 @@ export function toPromise(signal: AbortSignal): { promise: Promise; clean * * @param signals */ -export function getCombinedSignal( +export function getCombinedAbortSignal( signals: AbortSignal[] ): { signal: AbortSignal; cleanup: () => void } { const controller = new AbortController(); @@ -69,7 +71,7 @@ export function getCombinedSignal( if (signals.some((signal) => signal.aborted)) { controller.abort(); } else { - const promises = signals.map((signal) => toPromise(signal)); + const promises = signals.map((signal) => abortSignalToPromise(signal)); cleanup = () => { promises.forEach((p) => p.cleanup()); controller.signal.removeEventListener('abort', cleanup); diff --git a/src/plugins/kibana_utils/common/index.ts b/src/plugins/kibana_utils/common/index.ts index e09290c811c7b..a49b7100594ba 100644 --- a/src/plugins/kibana_utils/common/index.ts +++ b/src/plugins/kibana_utils/common/index.ts @@ -24,6 +24,7 @@ export * from './ui'; export * from './state_containers'; export * from './typed_json'; export * from './errors'; +export { AbortError, abortSignalToPromise, getCombinedAbortSignal } from './abort_utils'; export { createGetterSetter, Get, Set } from './create_getter_setter'; export { distinctUntilChangedWithInitialValue } from './distinct_until_changed_with_initial_value'; export { url } from './url'; diff --git a/src/plugins/kibana_utils/public/index.ts b/src/plugins/kibana_utils/public/index.ts index 9ba42d39139da..46a0cc4a10f00 100644 --- a/src/plugins/kibana_utils/public/index.ts +++ b/src/plugins/kibana_utils/public/index.ts @@ -18,12 +18,15 @@ */ export { + AbortError, + abortSignalToPromise, calculateObjectHash, defer, Defer, fieldWildcardFilter, fieldWildcardMatcher, Get, + getCombinedAbortSignal, JsonArray, JsonObject, JsonValue, diff --git a/src/plugins/kibana_utils/server/index.ts b/src/plugins/kibana_utils/server/index.ts index bf3361d1e5369..d994a4940bdfd 100644 --- a/src/plugins/kibana_utils/server/index.ts +++ b/src/plugins/kibana_utils/server/index.ts @@ -18,10 +18,13 @@ */ export { + AbortError, + abortSignalToPromise, createGetterSetter, fieldWildcardFilter, fieldWildcardMatcher, Get, + getCombinedAbortSignal, Set, url, } from '../common'; diff --git a/src/plugins/ui_actions/public/public.api.md b/src/plugins/ui_actions/public/public.api.md index 8393f7480d4e4..3e40c94e116fb 100644 --- a/src/plugins/ui_actions/public/public.api.md +++ b/src/plugins/ui_actions/public/public.api.md @@ -233,7 +233,7 @@ export class UiActionsService { // // (undocumented) protected readonly actions: ActionRegistry; - readonly addTriggerAction: (triggerId: T, action: UiActionsActionDefinition | Action) => void; + readonly addTriggerAction: (triggerId: T, action: UiActionsActionDefinition | Action) => void; // (undocumented) readonly attachAction: (triggerId: T, actionId: string) => void; readonly clear: () => void; @@ -247,21 +247,21 @@ export class UiActionsService { readonly executionService: UiActionsExecutionService; readonly fork: () => UiActionsService; // (undocumented) - readonly getAction: >(id: string) => Action, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK">; + readonly getAction: >(id: string) => Action, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION">; // Warning: (ae-forgotten-export) The symbol "TriggerContract" needs to be exported by the entry point index.d.ts // // (undocumented) readonly getTrigger: (triggerId: T) => TriggerContract; // (undocumented) - readonly getTriggerActions: (triggerId: T) => Action[]; + readonly getTriggerActions: (triggerId: T) => Action[]; // (undocumented) - readonly getTriggerCompatibleActions: (triggerId: T, context: TriggerContextMapping[T]) => Promise[]>; + readonly getTriggerCompatibleActions: (triggerId: T, context: TriggerContextMapping[T]) => Promise[]>; // (undocumented) readonly hasAction: (actionId: string) => boolean; // Warning: (ae-forgotten-export) The symbol "ActionContext" needs to be exported by the entry point index.d.ts // // (undocumented) - readonly registerAction: >(definition: A) => Action, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK">; + readonly registerAction: >(definition: A) => Action, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION">; // (undocumented) readonly registerTrigger: (trigger: Trigger) => void; // Warning: (ae-forgotten-export) The symbol "TriggerRegistry" needs to be exported by the entry point index.d.ts diff --git a/src/plugins/usage_collection/server/routes/stats/stats.ts b/src/plugins/usage_collection/server/routes/stats/stats.ts index ef64d15fabc2d..d38250067053c 100644 --- a/src/plugins/usage_collection/server/routes/stats/stats.ts +++ b/src/plugins/usage_collection/server/routes/stats/stats.ts @@ -73,8 +73,9 @@ export function registerStatsRoute({ return collectorSet.toObject(usage); }; - const getClusterUuid = async (callCluster: LegacyAPICaller): Promise => { - const { cluster_uuid: uuid } = await callCluster('info', { filterPath: 'cluster_uuid' }); + const getClusterUuid = async (asCurrentUser: ElasticsearchClient): Promise => { + const { body } = await asCurrentUser.info({ filter_path: 'cluster_uuid' }); + const { cluster_uuid: uuid } = body; return uuid; }; @@ -103,7 +104,7 @@ export function registerStatsRoute({ let extended; if (isExtended) { const callCluster = context.core.elasticsearch.legacy.client.callAsCurrentUser; - const esClient = context.core.elasticsearch.client.asCurrentUser; + const { asCurrentUser } = context.core.elasticsearch.client; const savedObjectsClient = context.core.savedObjects.client; if (shouldGetUsage) { @@ -114,9 +115,12 @@ export function registerStatsRoute({ } const usagePromise = shouldGetUsage - ? getUsage(callCluster, esClient, savedObjectsClient) + ? getUsage(callCluster, asCurrentUser, savedObjectsClient) : Promise.resolve({}); - const [usage, clusterUuid] = await Promise.all([usagePromise, getClusterUuid(callCluster)]); + const [usage, clusterUuid] = await Promise.all([ + usagePromise, + getClusterUuid(asCurrentUser), + ]); let modifiedUsage = usage; if (isLegacy) { diff --git a/src/plugins/vis_type_timelion/public/helpers/timelion_request_handler.ts b/src/plugins/vis_type_timelion/public/helpers/timelion_request_handler.ts index 1f0ac8b2b9392..7a630f36b51f4 100644 --- a/src/plugins/vis_type_timelion/public/helpers/timelion_request_handler.ts +++ b/src/plugins/vis_type_timelion/public/helpers/timelion_request_handler.ts @@ -18,8 +18,7 @@ */ import { i18n } from '@kbn/i18n'; -import { KIBANA_CONTEXT_NAME } from 'src/plugins/expressions/public'; -import { TimeRange, Filter, esQuery, Query } from '../../../data/public'; +import { KibanaContext, TimeRange, Filter, esQuery, Query } from '../../../data/public'; import { TimelionVisDependencies } from '../plugin'; import { getTimezone } from './get_timezone'; import { TimelionVisParams } from '../timelion_vis_fn'; @@ -59,7 +58,7 @@ export interface TimelionSuccessResponse { sheet: Sheet[]; stats: Stats; visType: string; - type: KIBANA_CONTEXT_NAME; + type: KibanaContext['type']; } export function getTimelionRequestHandler({ diff --git a/src/plugins/vis_type_timelion/public/timelion_vis_fn.ts b/src/plugins/vis_type_timelion/public/timelion_vis_fn.ts index a0cd410e197ff..2e8878b11e915 100644 --- a/src/plugins/vis_type_timelion/public/timelion_vis_fn.ts +++ b/src/plugins/vis_type_timelion/public/timelion_vis_fn.ts @@ -19,18 +19,14 @@ import { get } from 'lodash'; import { i18n } from '@kbn/i18n'; -import { - ExpressionFunctionDefinition, - KibanaContext, - Render, -} from 'src/plugins/expressions/public'; +import { ExpressionFunctionDefinition, Render } from 'src/plugins/expressions/public'; import { getTimelionRequestHandler, TimelionSuccessResponse, } from './helpers/timelion_request_handler'; import { TIMELION_VIS_NAME } from './timelion_vis_type'; import { TimelionVisDependencies } from './plugin'; -import { Filter, Query, TimeRange } from '../../data/common'; +import { KibanaContext, Filter, Query, TimeRange } from '../../data/public'; type Input = KibanaContext | null; type Output = Promise>; diff --git a/src/plugins/vis_type_timeseries/common/types.ts b/src/plugins/vis_type_timeseries/common/types.ts index 4520069244527..8973060848b41 100644 --- a/src/plugins/vis_type_timeseries/common/types.ts +++ b/src/plugins/vis_type_timeseries/common/types.ts @@ -18,8 +18,9 @@ */ import { TypeOf } from '@kbn/config-schema'; -import { metricsItems, panel, seriesItems } from './vis_schema'; +import { metricsItems, panel, seriesItems, visPayloadSchema } from './vis_schema'; export type SeriesItemsSchema = TypeOf; export type MetricsItemsSchema = TypeOf; export type PanelSchema = TypeOf; +export type VisPayload = TypeOf; diff --git a/src/plugins/vis_type_timeseries/common/vis_schema.ts b/src/plugins/vis_type_timeseries/common/vis_schema.ts index 40f776050617e..27f09fb574b0f 100644 --- a/src/plugins/vis_type_timeseries/common/vis_schema.ts +++ b/src/plugins/vis_type_timeseries/common/vis_schema.ts @@ -273,4 +273,5 @@ export const visPayloadSchema = schema.object({ min: stringRequired, max: stringRequired, }), + sessionId: schema.maybe(schema.string()), }); diff --git a/src/plugins/vis_type_timeseries/public/metrics_fn.ts b/src/plugins/vis_type_timeseries/public/metrics_fn.ts index b573225feaab1..8652d703f963e 100644 --- a/src/plugins/vis_type_timeseries/public/metrics_fn.ts +++ b/src/plugins/vis_type_timeseries/public/metrics_fn.ts @@ -19,7 +19,8 @@ import { get } from 'lodash'; import { i18n } from '@kbn/i18n'; -import { ExpressionFunctionDefinition, KibanaContext, Render } from '../../expressions/public'; +import { KibanaContext } from '../../data/public'; +import { ExpressionFunctionDefinition, Render } from '../../expressions/public'; // @ts-ignore import { metricsRequestHandler } from './request_handler'; diff --git a/src/plugins/vis_type_timeseries/public/request_handler.js b/src/plugins/vis_type_timeseries/public/request_handler.js index e33d0e254f609..12b7f3d417ef6 100644 --- a/src/plugins/vis_type_timeseries/public/request_handler.js +++ b/src/plugins/vis_type_timeseries/public/request_handler.js @@ -32,7 +32,8 @@ export const metricsRequestHandler = async ({ const config = getUISettings(); const timezone = getTimezone(config); const uiStateObj = uiState.get(visParams.type, {}); - const parsedTimeRange = getDataStart().query.timefilter.timefilter.calculateBounds(timeRange); + const dataSearch = getDataStart(); + const parsedTimeRange = dataSearch.query.timefilter.timefilter.calculateBounds(timeRange); const scaledDataFormat = config.get('dateFormat:scaled'); const dateFormat = config.get('dateFormat'); @@ -53,6 +54,7 @@ export const metricsRequestHandler = async ({ panels: [visParams], state: uiStateObj, savedObjectId: savedObjectId || 'unsaved', + sessionId: dataSearch.search.session.getSessionId(), }), }); diff --git a/src/plugins/vis_type_timeseries/server/lib/get_fields.ts b/src/plugins/vis_type_timeseries/server/lib/get_fields.ts index b52188129f77f..dc49e280a2bb7 100644 --- a/src/plugins/vis_type_timeseries/server/lib/get_fields.ts +++ b/src/plugins/vis_type_timeseries/server/lib/get_fields.ts @@ -62,10 +62,12 @@ export async function getFields( let indexPatternString = indexPattern; if (!indexPatternString) { - const [{ savedObjects }, { data }] = await framework.core.getStartServices(); + const [{ savedObjects, elasticsearch }, { data }] = await framework.core.getStartServices(); const savedObjectsClient = savedObjects.getScopedClient(request); + const clusterClient = elasticsearch.client.asScoped(request).asCurrentUser; const indexPatternsService = await data.indexPatterns.indexPatternsServiceFactory( - savedObjectsClient + savedObjectsClient, + clusterClient ); const defaultIndexPattern = await indexPatternsService.getDefault(); indexPatternString = get(defaultIndexPattern, 'title', ''); diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.test.js b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.test.js index 9710f7daf69b6..2c38e883cd69f 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.test.js +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.test.js @@ -28,6 +28,7 @@ describe('AbstractSearchStrategy', () => { beforeEach(() => { mockedFields = {}; req = { + payload: {}, pre: { indexPatternsService: { getFieldsForWildcard: jest.fn().mockReturnValue(mockedFields), @@ -60,6 +61,9 @@ describe('AbstractSearchStrategy', () => { const responses = await abstractSearchStrategy.search( { + payload: { + sessionId: 1, + }, requestContext: { search: { search: searchFn }, }, @@ -76,7 +80,9 @@ describe('AbstractSearchStrategy', () => { }, indexType: undefined, }, - {} + { + sessionId: 1, + } ); }); }); diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts index eb22fcb1dd689..b1e21edf8b588 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts @@ -23,8 +23,10 @@ import { IUiSettingsClient, SavedObjectsClientContract, } from 'kibana/server'; + import { Framework } from '../../../plugin'; import { IndexPatternsFetcher } from '../../../../../data/server'; +import { VisPayload } from '../../../../common/types'; /** * ReqFacade is a regular KibanaRequest object extended with additional service @@ -32,17 +34,17 @@ import { IndexPatternsFetcher } from '../../../../../data/server'; * * This will be replaced by standard KibanaRequest and RequestContext objects in a later version. */ -export type ReqFacade = FakeRequest & { +export interface ReqFacade extends FakeRequest { requestContext: RequestHandlerContext; framework: Framework; - payload: unknown; + payload: T; pre: { indexPatternsService?: IndexPatternsFetcher; }; getUiSettingsService: () => IUiSettingsClient; getSavedObjectsClient: () => SavedObjectsClientContract; getEsShardTimeout: () => Promise; -}; +} export class AbstractSearchStrategy { public indexType?: string; @@ -53,8 +55,10 @@ export class AbstractSearchStrategy { this.additionalParams = additionalParams; } - async search(req: ReqFacade, bodies: any[], options = {}) { + async search(req: ReqFacade, bodies: any[], options = {}) { const requests: any[] = []; + const { sessionId } = req.payload; + bodies.forEach((body) => { requests.push( req.requestContext @@ -67,6 +71,7 @@ export class AbstractSearchStrategy { indexType: this.indexType, }, { + sessionId, ...options, } ) diff --git a/src/plugins/vis_type_vega/public/vega_fn.ts b/src/plugins/vis_type_vega/public/vega_fn.ts index 25d4e76c336b3..5a8113aeeea11 100644 --- a/src/plugins/vis_type_vega/public/vega_fn.ts +++ b/src/plugins/vis_type_vega/public/vega_fn.ts @@ -19,16 +19,12 @@ import { get } from 'lodash'; import { i18n } from '@kbn/i18n'; -import { - ExecutionContext, - ExpressionFunctionDefinition, - KibanaContext, - Render, -} from '../../expressions/public'; +import { ExecutionContextSearch } from '../../data/public'; +import { ExecutionContext, ExpressionFunctionDefinition, Render } from '../../expressions/public'; import { VegaVisualizationDependencies } from './plugin'; import { createVegaRequestHandler } from './vega_request_handler'; import { VegaInspectorAdapters } from './vega_inspector/index'; -import { TimeRange, Query } from '../../data/public'; +import { KibanaContext, TimeRange, Query } from '../../data/public'; import { VegaParser } from './data_model/vega_parser'; type Input = KibanaContext | null; @@ -51,7 +47,7 @@ export type VegaExpressionFunctionDefinition = ExpressionFunctionDefinition< Input, Arguments, Output, - ExecutionContext + ExecutionContext >; export const createVegaFn = ( diff --git a/test/api_integration/apis/saved_objects/find.js b/test/api_integration/apis/saved_objects/find.js index c2e36b4a669ff..8e8730b1e574a 100644 --- a/test/api_integration/apis/saved_objects/find.js +++ b/test/api_integration/apis/saved_objects/find.js @@ -160,7 +160,7 @@ export default function ({ getService }) { }); describe('wildcard namespace', () => { - it('should return 200 with individual responses from the default namespace', async () => + it('should return 200 with individual responses from the all namespaces', async () => await supertest .get('/api/saved_objects/_find?type=visualization&fields=title&namespaces=*') .expect(200) @@ -168,7 +168,7 @@ export default function ({ getService }) { expect(resp.body).to.eql({ page: 1, per_page: 20, - total: 1, + total: 2, saved_objects: [ { type: 'visualization', @@ -189,6 +189,27 @@ export default function ({ getService }) { ], updated_at: '2017-09-21T18:51:23.794Z', }, + { + attributes: { + title: 'Count of requests', + }, + id: 'dd7caf20-9efd-11e7-acb3-3dab96693fab', + migrationVersion: { + visualization: '7.10.0', + }, + namespaces: ['foo-ns'], + references: [ + { + id: '91200a00-9efd-11e7-acb3-3dab96693fab', + name: 'kibanaSavedObjectMeta.searchSourceJSON.index', + type: 'index-pattern', + }, + ], + score: 0, + type: 'visualization', + updated_at: '2017-09-21T18:51:23.794Z', + version: 'WzYsMV0=', + }, ], }); expect(resp.body.saved_objects[0].migrationVersion).to.be.ok(); @@ -334,6 +355,70 @@ export default function ({ getService }) { }); }); + describe('searching for special characters', () => { + before(() => esArchiver.load('saved_objects/find_edgecases')); + after(() => esArchiver.unload('saved_objects/find_edgecases')); + + it('can search for objects with dashes', async () => + await supertest + .get('/api/saved_objects/_find') + .query({ + type: 'visualization', + search_fields: 'title', + search: 'my-vis*', + }) + .expect(200) + .then((resp) => { + const savedObjects = resp.body.saved_objects; + expect(savedObjects.map((so) => so.attributes.title)).to.eql(['my-visualization']); + })); + + it('can search with the prefix search character just after a special one', async () => + await supertest + .get('/api/saved_objects/_find') + .query({ + type: 'visualization', + search_fields: 'title', + search: 'my-*', + }) + .expect(200) + .then((resp) => { + const savedObjects = resp.body.saved_objects; + expect(savedObjects.map((so) => so.attributes.title)).to.eql(['my-visualization']); + })); + + it('can search for objects with asterisk', async () => + await supertest + .get('/api/saved_objects/_find') + .query({ + type: 'visualization', + search_fields: 'title', + search: 'some*vi*', + }) + .expect(200) + .then((resp) => { + const savedObjects = resp.body.saved_objects; + expect(savedObjects.map((so) => so.attributes.title)).to.eql(['some*visualization']); + })); + + it('can still search tokens by prefix', async () => + await supertest + .get('/api/saved_objects/_find') + .query({ + type: 'visualization', + search_fields: 'title', + search: 'visuali*', + }) + .expect(200) + .then((resp) => { + const savedObjects = resp.body.saved_objects; + expect(savedObjects.map((so) => so.attributes.title)).to.eql([ + 'my-visualization', + 'some*visualization', + ]); + })); + }); + describe('without kibana index', () => { before( async () => diff --git a/test/api_integration/fixtures/es_archiver/saved_objects/find_edgecases/data.json b/test/api_integration/fixtures/es_archiver/saved_objects/find_edgecases/data.json new file mode 100644 index 0000000000000..0c8b35fd3f499 --- /dev/null +++ b/test/api_integration/fixtures/es_archiver/saved_objects/find_edgecases/data.json @@ -0,0 +1,93 @@ +{ + "type": "doc", + "value": { + "index": ".kibana", + "id": "visualization:title-with-dash", + "source": { + "type": "visualization", + "updated_at": "2017-09-21T18:51:23.794Z", + "visualization": { + "title": "my-visualization", + "visState": "{}", + "uiStateJSON": "{\"spy\":{\"mode\":{\"name\":null,\"fill\":false}}}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[],\"query\":{\"query\":\"\",\"language\":\"lucene\"}}" + } + }, + "references": [] + } + } +} + +{ + "type": "doc", + "value": { + "index": ".kibana", + "id": "visualization:title-with-asterisk", + "source": { + "type": "visualization", + "updated_at": "2017-09-21T18:51:23.794Z", + "visualization": { + "title": "some*visualization", + "visState": "{}", + "uiStateJSON": "{\"spy\":{\"mode\":{\"name\":null,\"fill\":false}}}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[],\"query\":{\"query\":\"\",\"language\":\"lucene\"}}" + } + }, + "references": [] + } + } +} + + +{ + "type": "doc", + "value": { + "index": ".kibana", + "id": "visualization:noise-1", + "source": { + "type": "visualization", + "updated_at": "2017-09-21T18:51:23.794Z", + "visualization": { + "title": "Just some noise in the dataset", + "visState": "{}", + "uiStateJSON": "{\"spy\":{\"mode\":{\"name\":null,\"fill\":false}}}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[],\"query\":{\"query\":\"\",\"language\":\"lucene\"}}" + } + }, + "references": [] + } + } +} + +{ + "type": "doc", + "value": { + "index": ".kibana", + "id": "visualization:noise-2", + "source": { + "type": "visualization", + "updated_at": "2017-09-21T18:51:23.794Z", + "visualization": { + "title": "Just some noise in the dataset", + "visState": "{}", + "uiStateJSON": "{\"spy\":{\"mode\":{\"name\":null,\"fill\":false}}}", + "description": "", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[],\"query\":{\"query\":\"\",\"language\":\"lucene\"}}" + } + }, + "references": [] + } + } +} + diff --git a/test/api_integration/fixtures/es_archiver/saved_objects/find_edgecases/mappings.json b/test/api_integration/fixtures/es_archiver/saved_objects/find_edgecases/mappings.json new file mode 100644 index 0000000000000..e601c43431437 --- /dev/null +++ b/test/api_integration/fixtures/es_archiver/saved_objects/find_edgecases/mappings.json @@ -0,0 +1,267 @@ +{ + "type": "index", + "value": { + "index": ".kibana", + "settings": { + "index": { + "number_of_shards": "1", + "number_of_replicas": "1" + } + }, + "mappings": { + "dynamic": "strict", + "properties": { + "config": { + "dynamic": "true", + "properties": { + "buildNum": { + "type": "keyword" + }, + "defaultIndex": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + }, + "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" + } + } + }, + "index-pattern": { + "properties": { + "fieldFormatMap": { + "type": "text" + }, + "fields": { + "type": "text" + }, + "intervalName": { + "type": "keyword" + }, + "notExpandable": { + "type": "boolean" + }, + "sourceFilters": { + "type": "text" + }, + "timeFieldName": { + "type": "keyword" + }, + "title": { + "type": "text" + } + } + }, + "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" + } + } + }, + "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" + } + } + }, + "namespace": { + "type": "keyword" + }, + "references": { + "properties": { + "id": { + "type": "keyword" + }, + "name": { + "type": "keyword" + }, + "type": { + "type": "keyword" + } + }, + "type": "nested" + }, + "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" + } + } + } + } + } + } +} diff --git a/test/functional/apps/management/_import_objects.ts b/test/functional/apps/management/_import_objects.ts index 4a7a85c738fc2..52428c944d666 100644 --- a/test/functional/apps/management/_import_objects.ts +++ b/test/functional/apps/management/_import_objects.ts @@ -37,7 +37,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { describe('import objects', function describeIndexTests() { describe('.ndjson file', () => { beforeEach(async function () { - // delete .kibana index and then wait for Kibana to re-create it await kibanaServer.uiSettings.replace({}); await PageObjects.settings.navigateTo(); await esArchiver.load('management'); @@ -471,16 +470,20 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { ); }); - it('should display an explicit error message when importing a file bigger than allowed', async () => { - await PageObjects.savedObjects.importFile( - path.join(__dirname, 'exports', '_import_too_big.ndjson') - ); + describe('when bigger than savedObjects.maxImportPayloadBytes (not Cloud)', function () { + // see --savedObjects.maxImportPayloadBytes in config file + this.tags(['skipCloud']); + it('should display an explicit error message when importing a file bigger than allowed', async () => { + await PageObjects.savedObjects.importFile( + path.join(__dirname, 'exports', '_import_too_big.ndjson') + ); - await PageObjects.savedObjects.checkImportError(); + await PageObjects.savedObjects.checkImportError(); - const errorText = await PageObjects.savedObjects.getImportErrorText(); + const errorText = await PageObjects.savedObjects.getImportErrorText(); - expect(errorText).to.contain(`Payload content length greater than maximum allowed`); + expect(errorText).to.contain(`Payload content length greater than maximum allowed`); + }); }); it('should display an explicit error message when importing an invalid file', async () => { diff --git a/test/functional/apps/management/_mgmt_import_saved_objects.js b/test/functional/apps/management/_mgmt_import_saved_objects.js index 3a9f8665fd33b..d479a7006d0f8 100644 --- a/test/functional/apps/management/_mgmt_import_saved_objects.js +++ b/test/functional/apps/management/_mgmt_import_saved_objects.js @@ -29,6 +29,7 @@ export default function ({ getService, getPageObjects }) { describe('mgmt saved objects', function describeIndexTests() { beforeEach(async function () { + await esArchiver.load('empty_kibana'); await esArchiver.load('discover'); await PageObjects.settings.navigateTo(); }); diff --git a/test/functional/apps/management/_scripted_fields.js b/test/functional/apps/management/_scripted_fields.js index 6da9ebed0538a..5ca01f239e762 100644 --- a/test/functional/apps/management/_scripted_fields.js +++ b/test/functional/apps/management/_scripted_fields.js @@ -198,35 +198,44 @@ export default function ({ getService, getPageObjects }) { }); it('should visualize scripted field in vertical bar chart', async function () { - const expectedChartValues = [ - ['14', '31'], - ['10', '29'], - ['7', '24'], - ['11', '24'], - ['12', '23'], - ['20', '23'], - ['19', '21'], - ['6', '20'], - ['17', '20'], - ['30', '20'], - ['13', '19'], - ['18', '18'], - ['16', '17'], - ['5', '16'], - ['8', '16'], - ['15', '14'], - ['3', '13'], - ['2', '12'], - ['9', '10'], - ['4', '9'], - ]; await filterBar.removeAllFilters(); await PageObjects.discover.clickFieldListItemVisualize(scriptedPainlessFieldName); await PageObjects.header.waitUntilLoadingHasFinished(); - await inspector.open(); - await inspector.setTablePageSize(50); - await inspector.expectTableData(expectedChartValues); + if (await PageObjects.common.isOss()) { + // OSS renders a vertical bar chart and we check the data in the Inspect panel + const expectedChartValues = [ + ['14', '31'], + ['10', '29'], + ['7', '24'], + ['11', '24'], + ['12', '23'], + ['20', '23'], + ['19', '21'], + ['6', '20'], + ['17', '20'], + ['30', '20'], + ['13', '19'], + ['18', '18'], + ['16', '17'], + ['5', '16'], + ['8', '16'], + ['15', '14'], + ['3', '13'], + ['2', '12'], + ['9', '10'], + ['4', '9'], + ]; + + await inspector.open(); + await inspector.setTablePageSize(50); + await inspector.expectTableData(expectedChartValues); + } else { + // verify Lens opens a visualization + expect(await testSubjects.getVisibleTextAll('lns-dimensionTrigger')).to.contain( + 'Average of ram_Pain1' + ); + } }); }); @@ -309,11 +318,19 @@ export default function ({ getService, getPageObjects }) { it('should visualize scripted field in vertical bar chart', async function () { await PageObjects.discover.clickFieldListItemVisualize(scriptedPainlessFieldName2); await PageObjects.header.waitUntilLoadingHasFinished(); - await inspector.open(); - await inspector.expectTableData([ - ['good', '359'], - ['bad', '27'], - ]); + if (await PageObjects.common.isOss()) { + // OSS renders a vertical bar chart and we check the data in the Inspect panel + await inspector.open(); + await inspector.expectTableData([ + ['good', '359'], + ['bad', '27'], + ]); + } else { + // verify Lens opens a visualization + expect(await testSubjects.getVisibleTextAll('lns-dimensionTrigger')).to.contain( + 'Top values of painString' + ); + } }); }); @@ -397,11 +414,19 @@ export default function ({ getService, getPageObjects }) { it('should visualize scripted field in vertical bar chart', async function () { await PageObjects.discover.clickFieldListItemVisualize(scriptedPainlessFieldName2); await PageObjects.header.waitUntilLoadingHasFinished(); - await inspector.open(); - await inspector.expectTableData([ - ['true', '359'], - ['false', '27'], - ]); + if (await PageObjects.common.isOss()) { + // OSS renders a vertical bar chart and we check the data in the Inspect panel + await inspector.open(); + await inspector.expectTableData([ + ['true', '359'], + ['false', '27'], + ]); + } else { + // verify Lens opens a visualization + expect(await testSubjects.getVisibleTextAll('lns-dimensionTrigger')).to.contain( + 'Top values of painBool' + ); + } }); }); @@ -488,30 +513,39 @@ export default function ({ getService, getPageObjects }) { it('should visualize scripted field in vertical bar chart', async function () { await PageObjects.discover.clickFieldListItemVisualize(scriptedPainlessFieldName2); await PageObjects.header.waitUntilLoadingHasFinished(); - await inspector.open(); - await inspector.setTablePageSize(50); - await inspector.expectTableData([ - ['2015-09-17 20:00', '1'], - ['2015-09-17 21:00', '1'], - ['2015-09-17 23:00', '1'], - ['2015-09-18 00:00', '1'], - ['2015-09-18 03:00', '1'], - ['2015-09-18 04:00', '1'], - ['2015-09-18 04:00', '1'], - ['2015-09-18 04:00', '1'], - ['2015-09-18 04:00', '1'], - ['2015-09-18 05:00', '1'], - ['2015-09-18 05:00', '1'], - ['2015-09-18 05:00', '1'], - ['2015-09-18 05:00', '1'], - ['2015-09-18 06:00', '1'], - ['2015-09-18 06:00', '1'], - ['2015-09-18 06:00', '1'], - ['2015-09-18 06:00', '1'], - ['2015-09-18 07:00', '1'], - ['2015-09-18 07:00', '1'], - ['2015-09-18 07:00', '1'], - ]); + + if (await PageObjects.common.isOss()) { + // OSS renders a vertical bar chart and we check the data in the Inspect panel + await inspector.open(); + await inspector.setTablePageSize(50); + await inspector.expectTableData([ + ['2015-09-17 20:00', '1'], + ['2015-09-17 21:00', '1'], + ['2015-09-17 23:00', '1'], + ['2015-09-18 00:00', '1'], + ['2015-09-18 03:00', '1'], + ['2015-09-18 04:00', '1'], + ['2015-09-18 04:00', '1'], + ['2015-09-18 04:00', '1'], + ['2015-09-18 04:00', '1'], + ['2015-09-18 05:00', '1'], + ['2015-09-18 05:00', '1'], + ['2015-09-18 05:00', '1'], + ['2015-09-18 05:00', '1'], + ['2015-09-18 06:00', '1'], + ['2015-09-18 06:00', '1'], + ['2015-09-18 06:00', '1'], + ['2015-09-18 06:00', '1'], + ['2015-09-18 07:00', '1'], + ['2015-09-18 07:00', '1'], + ['2015-09-18 07:00', '1'], + ]); + } else { + // verify Lens opens a visualization + expect(await testSubjects.getVisibleTextAll('lns-dimensionTrigger')).to.contain( + 'painDate' + ); + } }); }); }); diff --git a/test/plugin_functional/plugins/data_search/server/plugin.ts b/test/plugin_functional/plugins/data_search/server/plugin.ts index e016ef56802f3..ca22e82188403 100644 --- a/test/plugin_functional/plugins/data_search/server/plugin.ts +++ b/test/plugin_functional/plugins/data_search/server/plugin.ts @@ -58,14 +58,16 @@ export class DataSearchTestPlugin }, }, async (context, req, res) => { - const [{ savedObjects }, { data }] = await core.getStartServices(); + const [{ savedObjects, elasticsearch }, { data }] = await core.getStartServices(); const service = await data.search.searchSource.asScoped(req); + const clusterClient = elasticsearch.client.asScoped(req).asCurrentUser; const savedObjectsClient = savedObjects.getScopedClient(req); // Since the index pattern ID can change on each test run, we need // to look it up on the fly and insert it into the request. const indexPatterns = await data.indexPatterns.indexPatternsServiceFactory( - savedObjectsClient + savedObjectsClient, + clusterClient ); const ids = await indexPatterns.getIds(); // @ts-expect-error Force overwriting the request diff --git a/test/plugin_functional/plugins/index_patterns/server/plugin.ts b/test/plugin_functional/plugins/index_patterns/server/plugin.ts index a54502b740211..c05b71b834c70 100644 --- a/test/plugin_functional/plugins/index_patterns/server/plugin.ts +++ b/test/plugin_functional/plugins/index_patterns/server/plugin.ts @@ -36,13 +36,35 @@ export class IndexPatternsTestPlugin public setup(core: CoreSetup) { const router = core.http.createRouter(); + router.post( + { + path: '/api/index-patterns-plugin/create', + validate: { + body: schema.object({}, { unknowns: 'allow' }), + }, + }, + async (context, req, res) => { + const [{ savedObjects, elasticsearch }, { data }] = await core.getStartServices(); + const savedObjectsClient = savedObjects.getScopedClient(req); + const service = await data.indexPatterns.indexPatternsServiceFactory( + savedObjectsClient, + elasticsearch.client.asScoped(req).asCurrentUser + ); + const ids = await service.createAndSave(req.body); + return res.ok({ body: ids }); + } + ); + router.get( { path: '/api/index-patterns-plugin/get-all', validate: false }, async (context, req, res) => { - const [{ savedObjects }, { data }] = await core.getStartServices(); + const [{ savedObjects, elasticsearch }, { data }] = await core.getStartServices(); const savedObjectsClient = savedObjects.getScopedClient(req); - const service = await data.indexPatterns.indexPatternsServiceFactory(savedObjectsClient); - const ids = await service.getIds(); + const service = await data.indexPatterns.indexPatternsServiceFactory( + savedObjectsClient, + elasticsearch.client.asScoped(req).asCurrentUser + ); + const ids = await service.getIds(true); return res.ok({ body: ids }); } ); @@ -58,9 +80,12 @@ export class IndexPatternsTestPlugin }, async (context, req, res) => { const id = (req.params as Record).id; - const [{ savedObjects }, { data }] = await core.getStartServices(); + const [{ savedObjects, elasticsearch }, { data }] = await core.getStartServices(); const savedObjectsClient = savedObjects.getScopedClient(req); - const service = await data.indexPatterns.indexPatternsServiceFactory(savedObjectsClient); + const service = await data.indexPatterns.indexPatternsServiceFactory( + savedObjectsClient, + elasticsearch.client.asScoped(req).asCurrentUser + ); const ip = await service.get(id); return res.ok({ body: ip.toSpec() }); } @@ -76,10 +101,13 @@ export class IndexPatternsTestPlugin }, }, async (context, req, res) => { - const [{ savedObjects }, { data }] = await core.getStartServices(); + const [{ savedObjects, elasticsearch }, { data }] = await core.getStartServices(); const id = (req.params as Record).id; const savedObjectsClient = savedObjects.getScopedClient(req); - const service = await data.indexPatterns.indexPatternsServiceFactory(savedObjectsClient); + const service = await data.indexPatterns.indexPatternsServiceFactory( + savedObjectsClient, + elasticsearch.client.asScoped(req).asCurrentUser + ); const ip = await service.get(id); await service.updateSavedObject(ip); return res.ok(); @@ -96,10 +124,13 @@ export class IndexPatternsTestPlugin }, }, async (context, req, res) => { - const [{ savedObjects }, { data }] = await core.getStartServices(); + const [{ savedObjects, elasticsearch }, { data }] = await core.getStartServices(); const id = (req.params as Record).id; const savedObjectsClient = savedObjects.getScopedClient(req); - const service = await data.indexPatterns.indexPatternsServiceFactory(savedObjectsClient); + const service = await data.indexPatterns.indexPatternsServiceFactory( + savedObjectsClient, + elasticsearch.client.asScoped(req).asCurrentUser + ); await service.delete(id); return res.ok(); } diff --git a/test/plugin_functional/test_suites/data_plugin/index_patterns.ts b/test/plugin_functional/test_suites/data_plugin/index_patterns.ts index 2c846dc780311..2e94f61c7ded8 100644 --- a/test/plugin_functional/test_suites/data_plugin/index_patterns.ts +++ b/test/plugin_functional/test_suites/data_plugin/index_patterns.ts @@ -23,16 +23,25 @@ import '../../plugins/core_provider_plugin/types'; export default function ({ getService }: PluginFunctionalProviderContext) { const supertest = getService('supertest'); - // skipping the tests as it deletes index patterns created by other test causing unexpected failures - // https://github.com/elastic/kibana/issues/79886 - describe.skip('index patterns', function () { + describe('index patterns', function () { let indexPatternId = ''; - it('can get all ids', async () => { - const body = await (await supertest.get('/api/index-patterns-plugin/get-all').expect(200)) - .body; - indexPatternId = body[0]; - expect(body.length > 0).to.equal(true); + it('can create an index pattern', async () => { + const title = 'shakes*'; + const fieldFormats = { bytes: { id: 'bytes' } }; + const body = await ( + await supertest + .post('/api/index-patterns-plugin/create') + .set('kbn-xsrf', 'anything') + .send({ title, fieldFormats }) + .expect(200) + ).body; + + indexPatternId = body.id; + expect(body.id).not.empty(); + expect(body.title).to.equal(title); + expect(body.fields.length).to.equal(15); + expect(body.fieldFormatMap).to.eql(fieldFormats); }); it('can get index pattern by id', async () => { diff --git a/x-pack/.i18nrc.json b/x-pack/.i18nrc.json index 3b1e4faf80bce..2be68b797ba5f 100644 --- a/x-pack/.i18nrc.json +++ b/x-pack/.i18nrc.json @@ -28,7 +28,7 @@ "xpack.idxMgmt": "plugins/index_management", "xpack.indexLifecycleMgmt": "plugins/index_lifecycle_management", "xpack.infra": "plugins/infra", - "xpack.fleet": "plugins/ingest_manager", + "xpack.fleet": "plugins/fleet", "xpack.ingestPipelines": "plugins/ingest_pipelines", "xpack.lens": "plugins/lens", "xpack.licenseMgmt": "plugins/license_management", diff --git a/x-pack/examples/alerting_example/public/alert_types/astros.tsx b/x-pack/examples/alerting_example/public/alert_types/astros.tsx index 73c7dfea1263b..54f989b93e22f 100644 --- a/x-pack/examples/alerting_example/public/alert_types/astros.tsx +++ b/x-pack/examples/alerting_example/public/alert_types/astros.tsx @@ -127,9 +127,9 @@ export const PeopleinSpaceExpression: React.FunctionComponent - errs.map((e) => ( -

+ Object.entries(errors).map(([field, errs]: [string, string[]], fieldIndex) => + errs.map((e, index) => ( +

{field}:`: ${errs}`

)) diff --git a/x-pack/examples/alerting_example/server/alert_types/always_firing.ts b/x-pack/examples/alerting_example/server/alert_types/always_firing.ts index bb1cb0d97689b..d02406a23045e 100644 --- a/x-pack/examples/alerting_example/server/alert_types/always_firing.ts +++ b/x-pack/examples/alerting_example/server/alert_types/always_firing.ts @@ -5,25 +5,31 @@ */ import uuid from 'uuid'; -import { range } from 'lodash'; +import { range, random } from 'lodash'; import { AlertType } from '../../../../plugins/alerts/server'; import { DEFAULT_INSTANCES_TO_GENERATE, ALERTING_EXAMPLE_APP_ID } from '../../common/constants'; +const ACTION_GROUPS = [ + { id: 'small', name: 'small' }, + { id: 'medium', name: 'medium' }, + { id: 'large', name: 'large' }, +]; + export const alertType: AlertType = { id: 'example.always-firing', name: 'Always firing', - actionGroups: [{ id: 'default', name: 'default' }], - defaultActionGroupId: 'default', + actionGroups: ACTION_GROUPS, + defaultActionGroupId: 'small', async executor({ services, params: { instances = DEFAULT_INSTANCES_TO_GENERATE }, state }) { const count = (state.count ?? 0) + 1; range(instances) - .map(() => ({ id: uuid.v4() })) - .forEach((instance: { id: string }) => { + .map(() => ({ id: uuid.v4(), tshirtSize: ACTION_GROUPS[random(0, 2)].id! })) + .forEach((instance: { id: string; tshirtSize: string }) => { services .alertInstanceFactory(instance.id) .replaceState({ triggerdOnCycle: count }) - .scheduleActions('default'); + .scheduleActions(instance.tshirtSize); }); return { diff --git a/x-pack/plugins/actions/README.md b/x-pack/plugins/actions/README.md index 4fef9bc582d08..432a4bfff7a6b 100644 --- a/x-pack/plugins/actions/README.md +++ b/x-pack/plugins/actions/README.md @@ -69,18 +69,21 @@ Table of Contents - [`secrets`](#secrets-6) - [`params`](#params-6) - [`subActionParams (pushToService)`](#subactionparams-pushtoservice) + - [`subActionParams (getFields)`](#subactionparams-getfields-1) - [Jira](#jira) - [`config`](#config-7) - [`secrets`](#secrets-7) - [`params`](#params-7) - [`subActionParams (pushToService)`](#subactionparams-pushtoservice-1) - [`subActionParams (issueTypes)`](#subactionparams-issuetypes) + - [`subActionParams (getFields)`](#subactionparams-getfields-2) - [`subActionParams (pushToService)`](#subactionparams-pushtoservice-2) - [IBM Resilient](#ibm-resilient) - [`config`](#config-8) - [`secrets`](#secrets-8) - [`params`](#params-8) - [`subActionParams (pushToService)`](#subactionparams-pushtoservice-3) + - [`subActionParams (getFields)`](#subactionparams-getfields-3) - [Command Line Utility](#command-line-utility) - [Developing New Action Types](#developing-new-action-types) - [licensing](#licensing) @@ -563,7 +566,7 @@ The ServiceNow action uses the [V2 Table API](https://developer.servicenow.com/a | Property | Description | Type | | --------------- | ------------------------------------------------------------------------------------ | ------ | -| subAction | The sub action to perform. It can be `pushToService`, `handshake`, and `getIncident` | string | +| subAction | The sub action to perform. It can be `getFields`, `pushToService`, `handshake`, and `getIncident` | string | | subActionParams | The parameters of the sub action | object | #### `subActionParams (pushToService)` @@ -580,6 +583,10 @@ The ServiceNow action uses the [V2 Table API](https://developer.servicenow.com/a | urgency | The name of the urgency in ServiceNow. | string _(optional)_ | | impact | The name of the impact in ServiceNow. | string _(optional)_ | +#### `subActionParams (getFields)` + +No parameters for `getFields` sub-action. Provide an empty object `{}`. + --- ## Jira @@ -606,7 +613,7 @@ The Jira action uses the [V2 API](https://developer.atlassian.com/cloud/jira/pla | Property | Description | Type | | --------------- | ----------------------------------------------------------------------------------------------------------------------- | ------ | -| subAction | The sub action to perform. It can be `pushToService`, `handshake`, `getIncident`, `issueTypes`, and `fieldsByIssueType` | string | +| subAction | The sub action to perform. It can be `getFields`, `pushToService`, `handshake`, `getIncident`, `issueTypes`, and `fieldsByIssueType` | string | | subActionParams | The parameters of the sub action | object | #### `subActionParams (pushToService)` @@ -627,6 +634,10 @@ The Jira action uses the [V2 API](https://developer.atlassian.com/cloud/jira/pla No parameters for `issueTypes` sub-action. Provide an empty object `{}`. +#### `subActionParams (getFields)` + +No parameters for `getFields` sub-action. Provide an empty object `{}`. + #### `subActionParams (pushToService)` | Property | Description | Type | @@ -655,7 +666,7 @@ ID: `.resilient` | Property | Description | Type | | --------------- | ------------------------------------------------------------------------------------ | ------ | -| subAction | The sub action to perform. It can be `pushToService`, `handshake`, and `getIncident` | string | +| subAction | The sub action to perform. It can be `getFields`, `pushToService`, `handshake`, and `getIncident` | string | | subActionParams | The parameters of the sub action | object | #### `subActionParams (pushToService)` @@ -670,6 +681,10 @@ ID: `.resilient` | incidentTypes | An array with the ids of IBM Resilient incident types. | number[] _(optional)_ | | severityCode | IBM Resilient id of the severity code. | number _(optional)_ | +#### `subActionParams (getFields)` + +No parameters for `getFields` sub-action. Provide an empty object `{}`. + # Command Line Utility The [`kbn-action`](https://github.com/pmuellr/kbn-action) tool can be used to send HTTP requests to the Actions plugin. For instance, to create a Slack action from the `.slack` Action Type, use the following command: diff --git a/x-pack/plugins/actions/server/builtin_action_types/jira/api.test.ts b/x-pack/plugins/actions/server/builtin_action_types/jira/api.test.ts index e8fa9f76df778..5a7617ada1bf0 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/jira/api.test.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/jira/api.test.ts @@ -15,804 +15,792 @@ describe('api', () => { beforeEach(() => { externalService = externalServiceMock.create(); - jest.clearAllMocks(); }); - afterEach(() => { - jest.clearAllMocks(); - }); - - describe('pushToService', () => { - describe('create incident - cases', () => { - test('it creates an incident', async () => { - const params = { ...apiParams, externalId: null }; - const res = await api.pushToService({ - externalService, - mapping, - params, - logger: mockedLogger, - }); - - expect(res).toEqual({ - id: 'incident-1', - title: 'CK-1', - pushedDate: '2020-04-27T10:59:46.202Z', - url: 'https://siem-kibana.atlassian.net/browse/CK-1', - comments: [ - { - commentId: 'case-comment-1', - pushedDate: '2020-04-27T10:59:46.202Z', - }, - { - commentId: 'case-comment-2', - pushedDate: '2020-04-27T10:59:46.202Z', - }, - ], - }); - }); - - test('it creates an incident without comments', async () => { - const params = { ...apiParams, externalId: null, comments: [] }; - const res = await api.pushToService({ - externalService, - mapping, - params, - logger: mockedLogger, - }); - - expect(res).toEqual({ - id: 'incident-1', - title: 'CK-1', - pushedDate: '2020-04-27T10:59:46.202Z', - url: 'https://siem-kibana.atlassian.net/browse/CK-1', - }); - }); - - test('it calls createIncident correctly', async () => { - const params = { ...apiParams, externalId: null }; - await api.pushToService({ externalService, mapping, params, logger: mockedLogger }); - - expect(externalService.createIncident).toHaveBeenCalledWith({ - incident: { - labels: ['kibana', 'elastic'], - priority: 'High', - issueType: '10006', - parent: null, - description: - 'Incident description (created at 2020-04-27T10:59:46.202Z by Elastic User)', - summary: 'Incident title (created at 2020-04-27T10:59:46.202Z by Elastic User)', - }, - }); - expect(externalService.updateIncident).not.toHaveBeenCalled(); - }); - - test('it calls createIncident correctly without mapping', async () => { - const params = { ...apiParams, externalId: null }; - await api.pushToService({ externalService, mapping: null, params, logger: mockedLogger }); - - expect(externalService.createIncident).toHaveBeenCalledWith({ - incident: { - description: 'Incident description', - summary: 'Incident title', - issueType: '10006', - labels: ['kibana', 'elastic'], - priority: 'High', - parent: null, - }, - }); - expect(externalService.updateIncident).not.toHaveBeenCalled(); + describe('create incident - cases', () => { + test('it creates an incident', async () => { + const params = { ...apiParams, externalId: null }; + const res = await api.pushToService({ + externalService, + mapping, + params, + logger: mockedLogger, }); - test('it calls createComment correctly', async () => { - const params = { ...apiParams, externalId: null }; - await api.pushToService({ externalService, mapping, params, logger: mockedLogger }); - expect(externalService.createComment).toHaveBeenCalledTimes(2); - expect(externalService.createComment).toHaveBeenNthCalledWith(1, { - incidentId: 'incident-1', - comment: { + expect(res).toEqual({ + id: 'incident-1', + title: 'CK-1', + pushedDate: '2020-04-27T10:59:46.202Z', + url: 'https://siem-kibana.atlassian.net/browse/CK-1', + comments: [ + { commentId: 'case-comment-1', - comment: 'A comment (added at 2020-04-27T10:59:46.202Z by Elastic User)', - createdAt: '2020-04-27T10:59:46.202Z', - createdBy: { - fullName: 'Elastic User', - username: 'elastic', - }, - updatedAt: '2020-04-27T10:59:46.202Z', - updatedBy: { - fullName: 'Elastic User', - username: 'elastic', - }, + pushedDate: '2020-04-27T10:59:46.202Z', }, - }); - - expect(externalService.createComment).toHaveBeenNthCalledWith(2, { - incidentId: 'incident-1', - comment: { + { commentId: 'case-comment-2', - comment: 'Another comment (added at 2020-04-27T10:59:46.202Z by Elastic User)', - createdAt: '2020-04-27T10:59:46.202Z', - createdBy: { - fullName: 'Elastic User', - username: 'elastic', - }, - updatedAt: '2020-04-27T10:59:46.202Z', - updatedBy: { - fullName: 'Elastic User', - username: 'elastic', - }, + pushedDate: '2020-04-27T10:59:46.202Z', }, - }); + ], }); + }); - test('it calls createComment correctly without mapping', async () => { - const params = { ...apiParams, externalId: null }; - await api.pushToService({ externalService, mapping: null, params, logger: mockedLogger }); - expect(externalService.createComment).toHaveBeenCalledTimes(2); - expect(externalService.createComment).toHaveBeenNthCalledWith(1, { - incidentId: 'incident-1', - comment: { - commentId: 'case-comment-1', - comment: 'A comment', - createdAt: '2020-04-27T10:59:46.202Z', - createdBy: { - fullName: 'Elastic User', - username: 'elastic', - }, - updatedAt: '2020-04-27T10:59:46.202Z', - updatedBy: { - fullName: 'Elastic User', - username: 'elastic', - }, - }, - }); + test('it creates an incident without comments', async () => { + const params = { ...apiParams, externalId: null, comments: [] }; + const res = await api.pushToService({ + externalService, + mapping, + params, + logger: mockedLogger, + }); - expect(externalService.createComment).toHaveBeenNthCalledWith(2, { - incidentId: 'incident-1', - comment: { - commentId: 'case-comment-2', - comment: 'Another comment', - createdAt: '2020-04-27T10:59:46.202Z', - createdBy: { - fullName: 'Elastic User', - username: 'elastic', - }, - updatedAt: '2020-04-27T10:59:46.202Z', - updatedBy: { - fullName: 'Elastic User', - username: 'elastic', - }, - }, - }); + expect(res).toEqual({ + id: 'incident-1', + title: 'CK-1', + pushedDate: '2020-04-27T10:59:46.202Z', + url: 'https://siem-kibana.atlassian.net/browse/CK-1', }); }); - describe('update incident', () => { - test('it updates an incident', async () => { - const res = await api.pushToService({ - externalService, - mapping, - params: apiParams, - logger: mockedLogger, - }); - - expect(res).toEqual({ - id: 'incident-1', - title: 'CK-1', - pushedDate: '2020-04-27T10:59:46.202Z', - url: 'https://siem-kibana.atlassian.net/browse/CK-1', - comments: [ - { - commentId: 'case-comment-1', - pushedDate: '2020-04-27T10:59:46.202Z', - }, - { - commentId: 'case-comment-2', - pushedDate: '2020-04-27T10:59:46.202Z', - }, - ], - }); - }); - - test('it updates an incident without comments', async () => { - const params = { ...apiParams, comments: [] }; - const res = await api.pushToService({ - externalService, - mapping, - params, - logger: mockedLogger, - }); - - expect(res).toEqual({ - id: 'incident-1', - title: 'CK-1', - pushedDate: '2020-04-27T10:59:46.202Z', - url: 'https://siem-kibana.atlassian.net/browse/CK-1', - }); - }); - - test('it calls updateIncident correctly', async () => { - const params = { ...apiParams }; - await api.pushToService({ externalService, mapping, params, logger: mockedLogger }); - - expect(externalService.updateIncident).toHaveBeenCalledWith({ - incidentId: 'incident-3', - incident: { - labels: ['kibana', 'elastic'], - priority: 'High', - issueType: '10006', - parent: null, - description: - 'Incident description (updated at 2020-04-27T10:59:46.202Z by Elastic User)', - summary: 'Incident title (updated at 2020-04-27T10:59:46.202Z by Elastic User)', + test('it calls createIncident correctly', async () => { + const params = { ...apiParams, externalId: null }; + await api.pushToService({ externalService, mapping, params, logger: mockedLogger }); + + expect(externalService.createIncident).toHaveBeenCalledWith({ + incident: { + labels: ['kibana', 'elastic'], + priority: 'High', + issueType: '10006', + parent: null, + description: 'Incident description (created at 2020-04-27T10:59:46.202Z by Elastic User)', + summary: 'Incident title (created at 2020-04-27T10:59:46.202Z by Elastic User)', + }, + }); + expect(externalService.updateIncident).not.toHaveBeenCalled(); + }); + + test('it calls createIncident correctly without mapping', async () => { + const params = { ...apiParams, externalId: null }; + await api.pushToService({ externalService, mapping: null, params, logger: mockedLogger }); + + expect(externalService.createIncident).toHaveBeenCalledWith({ + incident: { + description: 'Incident description', + summary: 'Incident title', + issueType: '10006', + labels: ['kibana', 'elastic'], + priority: 'High', + parent: null, + }, + }); + expect(externalService.updateIncident).not.toHaveBeenCalled(); + }); + + test('it calls createComment correctly', async () => { + const params = { ...apiParams, externalId: null }; + await api.pushToService({ externalService, mapping, params, logger: mockedLogger }); + expect(externalService.createComment).toHaveBeenCalledTimes(2); + expect(externalService.createComment).toHaveBeenNthCalledWith(1, { + incidentId: 'incident-1', + comment: { + commentId: 'case-comment-1', + comment: 'A comment (added at 2020-04-27T10:59:46.202Z by Elastic User)', + createdAt: '2020-04-27T10:59:46.202Z', + createdBy: { + fullName: 'Elastic User', + username: 'elastic', }, - }); - expect(externalService.createIncident).not.toHaveBeenCalled(); - }); - - test('it calls updateIncident correctly without mapping', async () => { - const params = { ...apiParams }; - await api.pushToService({ externalService, mapping: null, params, logger: mockedLogger }); - - expect(externalService.updateIncident).toHaveBeenCalledWith({ - incidentId: 'incident-3', - incident: { - description: 'Incident description', - summary: 'Incident title', - issueType: '10006', - labels: ['kibana', 'elastic'], - priority: 'High', - parent: null, + updatedAt: '2020-04-27T10:59:46.202Z', + updatedBy: { + fullName: 'Elastic User', + username: 'elastic', }, - }); - expect(externalService.createIncident).not.toHaveBeenCalled(); + }, }); - test('it calls createComment correctly', async () => { - const params = { ...apiParams }; - await api.pushToService({ externalService, mapping, params, logger: mockedLogger }); - expect(externalService.createComment).toHaveBeenCalledTimes(2); - expect(externalService.createComment).toHaveBeenNthCalledWith(1, { - incidentId: 'incident-1', - comment: { - commentId: 'case-comment-1', - comment: 'A comment (added at 2020-04-27T10:59:46.202Z by Elastic User)', - createdAt: '2020-04-27T10:59:46.202Z', - createdBy: { - fullName: 'Elastic User', - username: 'elastic', - }, - updatedAt: '2020-04-27T10:59:46.202Z', - updatedBy: { - fullName: 'Elastic User', - username: 'elastic', - }, + expect(externalService.createComment).toHaveBeenNthCalledWith(2, { + incidentId: 'incident-1', + comment: { + commentId: 'case-comment-2', + comment: 'Another comment (added at 2020-04-27T10:59:46.202Z by Elastic User)', + createdAt: '2020-04-27T10:59:46.202Z', + createdBy: { + fullName: 'Elastic User', + username: 'elastic', }, - }); - - expect(externalService.createComment).toHaveBeenNthCalledWith(2, { - incidentId: 'incident-1', - comment: { - commentId: 'case-comment-2', - comment: 'Another comment (added at 2020-04-27T10:59:46.202Z by Elastic User)', - createdAt: '2020-04-27T10:59:46.202Z', - createdBy: { - fullName: 'Elastic User', - username: 'elastic', - }, - updatedAt: '2020-04-27T10:59:46.202Z', - updatedBy: { - fullName: 'Elastic User', - username: 'elastic', - }, + updatedAt: '2020-04-27T10:59:46.202Z', + updatedBy: { + fullName: 'Elastic User', + username: 'elastic', }, - }); + }, }); + }); - test('it calls createComment correctly without mapping', async () => { - const params = { ...apiParams }; - await api.pushToService({ externalService, mapping: null, params, logger: mockedLogger }); - expect(externalService.createComment).toHaveBeenCalledTimes(2); - expect(externalService.createComment).toHaveBeenNthCalledWith(1, { - incidentId: 'incident-1', - comment: { - commentId: 'case-comment-1', - comment: 'A comment', - createdAt: '2020-04-27T10:59:46.202Z', - createdBy: { - fullName: 'Elastic User', - username: 'elastic', - }, - updatedAt: '2020-04-27T10:59:46.202Z', - updatedBy: { - fullName: 'Elastic User', - username: 'elastic', - }, + test('it calls createComment correctly without mapping', async () => { + const params = { ...apiParams, externalId: null }; + await api.pushToService({ externalService, mapping: null, params, logger: mockedLogger }); + expect(externalService.createComment).toHaveBeenCalledTimes(2); + expect(externalService.createComment).toHaveBeenNthCalledWith(1, { + incidentId: 'incident-1', + comment: { + commentId: 'case-comment-1', + comment: 'A comment', + createdAt: '2020-04-27T10:59:46.202Z', + createdBy: { + fullName: 'Elastic User', + username: 'elastic', + }, + updatedAt: '2020-04-27T10:59:46.202Z', + updatedBy: { + fullName: 'Elastic User', + username: 'elastic', }, - }); + }, + }); - expect(externalService.createComment).toHaveBeenNthCalledWith(2, { - incidentId: 'incident-1', - comment: { - commentId: 'case-comment-2', - comment: 'Another comment', - createdAt: '2020-04-27T10:59:46.202Z', - createdBy: { - fullName: 'Elastic User', - username: 'elastic', - }, - updatedAt: '2020-04-27T10:59:46.202Z', - updatedBy: { - fullName: 'Elastic User', - username: 'elastic', - }, + expect(externalService.createComment).toHaveBeenNthCalledWith(2, { + incidentId: 'incident-1', + comment: { + commentId: 'case-comment-2', + comment: 'Another comment', + createdAt: '2020-04-27T10:59:46.202Z', + createdBy: { + fullName: 'Elastic User', + username: 'elastic', + }, + updatedAt: '2020-04-27T10:59:46.202Z', + updatedBy: { + fullName: 'Elastic User', + username: 'elastic', }, - }); + }, }); }); + }); - describe('issueTypes', () => { - test('it returns the issue types correctly', async () => { - const res = await api.issueTypes({ - externalService, - params: {}, - }); - expect(res).toEqual([ + describe('update incident', () => { + test('it updates an incident', async () => { + const res = await api.pushToService({ + externalService, + mapping, + params: apiParams, + logger: mockedLogger, + }); + + expect(res).toEqual({ + id: 'incident-1', + title: 'CK-1', + pushedDate: '2020-04-27T10:59:46.202Z', + url: 'https://siem-kibana.atlassian.net/browse/CK-1', + comments: [ { - id: '10006', - name: 'Task', + commentId: 'case-comment-1', + pushedDate: '2020-04-27T10:59:46.202Z', }, { - id: '10007', - name: 'Bug', + commentId: 'case-comment-2', + pushedDate: '2020-04-27T10:59:46.202Z', }, - ]); + ], }); }); - describe('fieldsByIssueType', () => { - test('it returns the fields correctly', async () => { - const res = await api.fieldsByIssueType({ - externalService, - params: { id: '10006' }, - }); - expect(res).toEqual({ - summary: { allowedValues: [], defaultValue: {} }, - priority: { - allowedValues: [ - { - name: 'Medium', - id: '3', - }, - ], - defaultValue: { name: 'Medium', id: '3' }, - }, - }); + test('it updates an incident without comments', async () => { + const params = { ...apiParams, comments: [] }; + const res = await api.pushToService({ + externalService, + mapping, + params, + logger: mockedLogger, + }); + + expect(res).toEqual({ + id: 'incident-1', + title: 'CK-1', + pushedDate: '2020-04-27T10:59:46.202Z', + url: 'https://siem-kibana.atlassian.net/browse/CK-1', }); }); - describe('getIssues', () => { - test('it returns the issues correctly', async () => { - const res = await api.issues({ - externalService, - params: { title: 'Title test' }, - }); - expect(res).toEqual([ - { - id: '10267', - key: 'RJ-107', - title: 'Test title', - }, - ]); + test('it calls updateIncident correctly', async () => { + const params = { ...apiParams }; + await api.pushToService({ externalService, mapping, params, logger: mockedLogger }); + + expect(externalService.updateIncident).toHaveBeenCalledWith({ + incidentId: 'incident-3', + incident: { + labels: ['kibana', 'elastic'], + priority: 'High', + issueType: '10006', + parent: null, + description: 'Incident description (updated at 2020-04-27T10:59:46.202Z by Elastic User)', + summary: 'Incident title (updated at 2020-04-27T10:59:46.202Z by Elastic User)', + }, }); + expect(externalService.createIncident).not.toHaveBeenCalled(); }); - describe('getIssue', () => { - test('it returns the issue correctly', async () => { - const res = await api.issue({ - externalService, - params: { id: 'RJ-107' }, - }); - expect(res).toEqual({ - id: '10267', - key: 'RJ-107', - title: 'Test title', - }); + test('it calls updateIncident correctly without mapping', async () => { + const params = { ...apiParams }; + await api.pushToService({ externalService, mapping: null, params, logger: mockedLogger }); + + expect(externalService.updateIncident).toHaveBeenCalledWith({ + incidentId: 'incident-3', + incident: { + description: 'Incident description', + summary: 'Incident title', + issueType: '10006', + labels: ['kibana', 'elastic'], + priority: 'High', + parent: null, + }, }); + expect(externalService.createIncident).not.toHaveBeenCalled(); }); - describe('mapping variations', () => { - test('overwrite & append', async () => { - mapping.set('title', { - target: 'summary', - actionType: 'overwrite', - }); - - mapping.set('description', { - target: 'description', - actionType: 'append', - }); - - mapping.set('comments', { - target: 'comments', - actionType: 'append', - }); - - mapping.set('summary', { - target: 'title', - actionType: 'overwrite', - }); - - await api.pushToService({ - externalService, - mapping, - params: apiParams, - logger: mockedLogger, - }); - expect(externalService.updateIncident).toHaveBeenCalledWith({ - incidentId: 'incident-3', - incident: { - labels: ['kibana', 'elastic'], - priority: 'High', - issueType: '10006', - parent: null, - summary: 'Incident title (updated at 2020-04-27T10:59:46.202Z by Elastic User)', - description: - 'description from jira \r\nIncident description (updated at 2020-04-27T10:59:46.202Z by Elastic User)', - }, - }); - }); - - test('nothing & append', async () => { - mapping.set('title', { - target: 'summary', - actionType: 'nothing', - }); - - mapping.set('description', { - target: 'description', - actionType: 'append', - }); - - mapping.set('comments', { - target: 'comments', - actionType: 'append', - }); - - mapping.set('summary', { - target: 'title', - actionType: 'nothing', - }); - - await api.pushToService({ - externalService, - mapping, - params: apiParams, - logger: mockedLogger, - }); - expect(externalService.updateIncident).toHaveBeenCalledWith({ - incidentId: 'incident-3', - incident: { - labels: ['kibana', 'elastic'], - priority: 'High', - issueType: '10006', - parent: null, - description: - 'description from jira \r\nIncident description (updated at 2020-04-27T10:59:46.202Z by Elastic User)', + test('it calls createComment correctly', async () => { + const params = { ...apiParams }; + await api.pushToService({ externalService, mapping, params, logger: mockedLogger }); + expect(externalService.createComment).toHaveBeenCalledTimes(2); + expect(externalService.createComment).toHaveBeenNthCalledWith(1, { + incidentId: 'incident-1', + comment: { + commentId: 'case-comment-1', + comment: 'A comment (added at 2020-04-27T10:59:46.202Z by Elastic User)', + createdAt: '2020-04-27T10:59:46.202Z', + createdBy: { + fullName: 'Elastic User', + username: 'elastic', }, - }); - }); - - test('append & append', async () => { - mapping.set('title', { - target: 'summary', - actionType: 'append', - }); - - mapping.set('description', { - target: 'description', - actionType: 'append', - }); - - mapping.set('comments', { - target: 'comments', - actionType: 'append', - }); - - mapping.set('summary', { - target: 'title', - actionType: 'append', - }); - - await api.pushToService({ - externalService, - mapping, - params: apiParams, - logger: mockedLogger, - }); - expect(externalService.updateIncident).toHaveBeenCalledWith({ - incidentId: 'incident-3', - incident: { - labels: ['kibana', 'elastic'], - priority: 'High', - issueType: '10006', - parent: null, - summary: - 'title from jira \r\nIncident title (updated at 2020-04-27T10:59:46.202Z by Elastic User)', - description: - 'description from jira \r\nIncident description (updated at 2020-04-27T10:59:46.202Z by Elastic User)', + updatedAt: '2020-04-27T10:59:46.202Z', + updatedBy: { + fullName: 'Elastic User', + username: 'elastic', }, - }); - }); - - test('nothing & nothing', async () => { - mapping.set('title', { - target: 'summary', - actionType: 'nothing', - }); - - mapping.set('description', { - target: 'description', - actionType: 'nothing', - }); - - mapping.set('comments', { - target: 'comments', - actionType: 'append', - }); - - mapping.set('summary', { - target: 'title', - actionType: 'nothing', - }); - - await api.pushToService({ - externalService, - mapping, - params: apiParams, - logger: mockedLogger, - }); - expect(externalService.updateIncident).toHaveBeenCalledWith({ - incidentId: 'incident-3', - incident: { - labels: ['kibana', 'elastic'], - priority: 'High', - issueType: '10006', - parent: null, + }, + }); + + expect(externalService.createComment).toHaveBeenNthCalledWith(2, { + incidentId: 'incident-1', + comment: { + commentId: 'case-comment-2', + comment: 'Another comment (added at 2020-04-27T10:59:46.202Z by Elastic User)', + createdAt: '2020-04-27T10:59:46.202Z', + createdBy: { + fullName: 'Elastic User', + username: 'elastic', }, - }); - }); - - test('overwrite & nothing', async () => { - mapping.set('title', { - target: 'summary', - actionType: 'overwrite', - }); - - mapping.set('description', { - target: 'description', - actionType: 'nothing', - }); - - mapping.set('comments', { - target: 'comments', - actionType: 'append', - }); - - mapping.set('summary', { - target: 'title', - actionType: 'overwrite', - }); - - await api.pushToService({ - externalService, - mapping, - params: apiParams, - logger: mockedLogger, - }); - expect(externalService.updateIncident).toHaveBeenCalledWith({ - incidentId: 'incident-3', - incident: { - labels: ['kibana', 'elastic'], - priority: 'High', - issueType: '10006', - parent: null, - summary: 'Incident title (updated at 2020-04-27T10:59:46.202Z by Elastic User)', + updatedAt: '2020-04-27T10:59:46.202Z', + updatedBy: { + fullName: 'Elastic User', + username: 'elastic', }, - }); - }); - - test('overwrite & overwrite', async () => { - mapping.set('title', { - target: 'summary', - actionType: 'overwrite', - }); - - mapping.set('description', { - target: 'description', - actionType: 'overwrite', - }); - - mapping.set('comments', { - target: 'comments', - actionType: 'append', - }); - - mapping.set('summary', { - target: 'title', - actionType: 'overwrite', - }); - - await api.pushToService({ - externalService, - mapping, - params: apiParams, - logger: mockedLogger, - }); - expect(externalService.updateIncident).toHaveBeenCalledWith({ - incidentId: 'incident-3', - incident: { - labels: ['kibana', 'elastic'], - priority: 'High', - issueType: '10006', - parent: null, - summary: 'Incident title (updated at 2020-04-27T10:59:46.202Z by Elastic User)', - description: - 'Incident description (updated at 2020-04-27T10:59:46.202Z by Elastic User)', + }, + }); + }); + + test('it calls createComment correctly without mapping', async () => { + const params = { ...apiParams }; + await api.pushToService({ externalService, mapping: null, params, logger: mockedLogger }); + expect(externalService.createComment).toHaveBeenCalledTimes(2); + expect(externalService.createComment).toHaveBeenNthCalledWith(1, { + incidentId: 'incident-1', + comment: { + commentId: 'case-comment-1', + comment: 'A comment', + createdAt: '2020-04-27T10:59:46.202Z', + createdBy: { + fullName: 'Elastic User', + username: 'elastic', }, - }); - }); - - test('nothing & overwrite', async () => { - mapping.set('title', { - target: 'summary', - actionType: 'nothing', - }); - - mapping.set('description', { - target: 'description', - actionType: 'overwrite', - }); - - mapping.set('comments', { - target: 'comments', - actionType: 'append', - }); - - mapping.set('summary', { - target: 'title', - actionType: 'nothing', - }); - - await api.pushToService({ - externalService, - mapping, - params: apiParams, - logger: mockedLogger, - }); - expect(externalService.updateIncident).toHaveBeenCalledWith({ - incidentId: 'incident-3', - incident: { - labels: ['kibana', 'elastic'], - priority: 'High', - issueType: '10006', - parent: null, - description: - 'Incident description (updated at 2020-04-27T10:59:46.202Z by Elastic User)', + updatedAt: '2020-04-27T10:59:46.202Z', + updatedBy: { + fullName: 'Elastic User', + username: 'elastic', }, - }); - }); - - test('append & overwrite', async () => { - mapping.set('title', { - target: 'summary', - actionType: 'append', - }); - - mapping.set('description', { - target: 'description', - actionType: 'overwrite', - }); - - mapping.set('comments', { - target: 'comments', - actionType: 'append', - }); - - mapping.set('summary', { - target: 'title', - actionType: 'append', - }); - - await api.pushToService({ - externalService, - mapping, - params: apiParams, - logger: mockedLogger, - }); - expect(externalService.updateIncident).toHaveBeenCalledWith({ - incidentId: 'incident-3', - incident: { - labels: ['kibana', 'elastic'], - priority: 'High', - issueType: '10006', - parent: null, - summary: - 'title from jira \r\nIncident title (updated at 2020-04-27T10:59:46.202Z by Elastic User)', - description: - 'Incident description (updated at 2020-04-27T10:59:46.202Z by Elastic User)', + }, + }); + + expect(externalService.createComment).toHaveBeenNthCalledWith(2, { + incidentId: 'incident-1', + comment: { + commentId: 'case-comment-2', + comment: 'Another comment', + createdAt: '2020-04-27T10:59:46.202Z', + createdBy: { + fullName: 'Elastic User', + username: 'elastic', }, - }); - }); - - test('append & nothing', async () => { - mapping.set('title', { - target: 'summary', - actionType: 'append', - }); - - mapping.set('description', { - target: 'description', - actionType: 'nothing', - }); - - mapping.set('comments', { - target: 'comments', - actionType: 'append', - }); - - mapping.set('summary', { - target: 'title', - actionType: 'append', - }); - - await api.pushToService({ - externalService, - mapping, - params: apiParams, - logger: mockedLogger, - }); - expect(externalService.updateIncident).toHaveBeenCalledWith({ - incidentId: 'incident-3', - incident: { - labels: ['kibana', 'elastic'], - priority: 'High', - issueType: '10006', - parent: null, - summary: - 'title from jira \r\nIncident title (updated at 2020-04-27T10:59:46.202Z by Elastic User)', + updatedAt: '2020-04-27T10:59:46.202Z', + updatedBy: { + fullName: 'Elastic User', + username: 'elastic', }, - }); - }); - - test('comment nothing', async () => { - mapping.set('title', { - target: 'summary', - actionType: 'overwrite', - }); - - mapping.set('description', { - target: 'description', - actionType: 'nothing', - }); - - mapping.set('comments', { - target: 'comments', - actionType: 'nothing', - }); - - mapping.set('summary', { - target: 'title', - actionType: 'overwrite', - }); - - await api.pushToService({ - externalService, - mapping, - params: apiParams, - logger: mockedLogger, - }); - expect(externalService.createComment).not.toHaveBeenCalled(); + }, + }); + }); + }); + + describe('issueTypes', () => { + test('it returns the issue types correctly', async () => { + const res = await api.issueTypes({ + externalService, + params: {}, + }); + expect(res).toEqual([ + { + id: '10006', + name: 'Task', + }, + { + id: '10007', + name: 'Bug', + }, + ]); + }); + }); + + describe('fieldsByIssueType', () => { + test('it returns the fields correctly', async () => { + const res = await api.fieldsByIssueType({ + externalService, + params: { id: '10006' }, + }); + expect(res).toEqual({ + summary: { allowedValues: [], defaultValue: {} }, + priority: { + allowedValues: [ + { + name: 'Medium', + id: '3', + }, + ], + defaultValue: { name: 'Medium', id: '3' }, + }, + }); + }); + }); + + describe('getIssues', () => { + test('it returns the issues correctly', async () => { + const res = await api.issues({ + externalService, + params: { title: 'Title test' }, + }); + expect(res).toEqual([ + { + id: '10267', + key: 'RJ-107', + title: 'Test title', + }, + ]); + }); + }); + + describe('getIssue', () => { + test('it returns the issue correctly', async () => { + const res = await api.issue({ + externalService, + params: { id: 'RJ-107' }, + }); + expect(res).toEqual({ + id: '10267', + key: 'RJ-107', + title: 'Test title', + }); + }); + }); + + describe('mapping variations', () => { + test('overwrite & append', async () => { + mapping.set('title', { + target: 'summary', + actionType: 'overwrite', + }); + + mapping.set('description', { + target: 'description', + actionType: 'append', + }); + + mapping.set('comments', { + target: 'comments', + actionType: 'append', + }); + + mapping.set('summary', { + target: 'title', + actionType: 'overwrite', + }); + + await api.pushToService({ + externalService, + mapping, + params: apiParams, + logger: mockedLogger, + }); + expect(externalService.updateIncident).toHaveBeenCalledWith({ + incidentId: 'incident-3', + incident: { + labels: ['kibana', 'elastic'], + priority: 'High', + issueType: '10006', + parent: null, + summary: 'Incident title (updated at 2020-04-27T10:59:46.202Z by Elastic User)', + description: + 'description from jira \r\nIncident description (updated at 2020-04-27T10:59:46.202Z by Elastic User)', + }, + }); + }); + + test('nothing & append', async () => { + mapping.set('title', { + target: 'summary', + actionType: 'nothing', + }); + + mapping.set('description', { + target: 'description', + actionType: 'append', + }); + + mapping.set('comments', { + target: 'comments', + actionType: 'append', + }); + + mapping.set('summary', { + target: 'title', + actionType: 'nothing', + }); + + await api.pushToService({ + externalService, + mapping, + params: apiParams, + logger: mockedLogger, + }); + expect(externalService.updateIncident).toHaveBeenCalledWith({ + incidentId: 'incident-3', + incident: { + labels: ['kibana', 'elastic'], + priority: 'High', + issueType: '10006', + parent: null, + description: + 'description from jira \r\nIncident description (updated at 2020-04-27T10:59:46.202Z by Elastic User)', + }, + }); + }); + + test('append & append', async () => { + mapping.set('title', { + target: 'summary', + actionType: 'append', + }); + + mapping.set('description', { + target: 'description', + actionType: 'append', + }); + + mapping.set('comments', { + target: 'comments', + actionType: 'append', + }); + + mapping.set('summary', { + target: 'title', + actionType: 'append', + }); + + await api.pushToService({ + externalService, + mapping, + params: apiParams, + logger: mockedLogger, + }); + expect(externalService.updateIncident).toHaveBeenCalledWith({ + incidentId: 'incident-3', + incident: { + labels: ['kibana', 'elastic'], + priority: 'High', + issueType: '10006', + parent: null, + summary: + 'title from jira \r\nIncident title (updated at 2020-04-27T10:59:46.202Z by Elastic User)', + description: + 'description from jira \r\nIncident description (updated at 2020-04-27T10:59:46.202Z by Elastic User)', + }, + }); + }); + + test('nothing & nothing', async () => { + mapping.set('title', { + target: 'summary', + actionType: 'nothing', + }); + + mapping.set('description', { + target: 'description', + actionType: 'nothing', + }); + + mapping.set('comments', { + target: 'comments', + actionType: 'append', + }); + + mapping.set('summary', { + target: 'title', + actionType: 'nothing', + }); + + await api.pushToService({ + externalService, + mapping, + params: apiParams, + logger: mockedLogger, + }); + expect(externalService.updateIncident).toHaveBeenCalledWith({ + incidentId: 'incident-3', + incident: { + labels: ['kibana', 'elastic'], + priority: 'High', + issueType: '10006', + parent: null, + }, + }); + }); + + test('overwrite & nothing', async () => { + mapping.set('title', { + target: 'summary', + actionType: 'overwrite', + }); + + mapping.set('description', { + target: 'description', + actionType: 'nothing', + }); + + mapping.set('comments', { + target: 'comments', + actionType: 'append', + }); + + mapping.set('summary', { + target: 'title', + actionType: 'overwrite', + }); + + await api.pushToService({ + externalService, + mapping, + params: apiParams, + logger: mockedLogger, + }); + expect(externalService.updateIncident).toHaveBeenCalledWith({ + incidentId: 'incident-3', + incident: { + labels: ['kibana', 'elastic'], + priority: 'High', + issueType: '10006', + parent: null, + summary: 'Incident title (updated at 2020-04-27T10:59:46.202Z by Elastic User)', + }, + }); + }); + + test('overwrite & overwrite', async () => { + mapping.set('title', { + target: 'summary', + actionType: 'overwrite', + }); + + mapping.set('description', { + target: 'description', + actionType: 'overwrite', + }); + + mapping.set('comments', { + target: 'comments', + actionType: 'append', + }); + + mapping.set('summary', { + target: 'title', + actionType: 'overwrite', + }); + + await api.pushToService({ + externalService, + mapping, + params: apiParams, + logger: mockedLogger, + }); + expect(externalService.updateIncident).toHaveBeenCalledWith({ + incidentId: 'incident-3', + incident: { + labels: ['kibana', 'elastic'], + priority: 'High', + issueType: '10006', + parent: null, + summary: 'Incident title (updated at 2020-04-27T10:59:46.202Z by Elastic User)', + description: 'Incident description (updated at 2020-04-27T10:59:46.202Z by Elastic User)', + }, + }); + }); + + test('nothing & overwrite', async () => { + mapping.set('title', { + target: 'summary', + actionType: 'nothing', + }); + + mapping.set('description', { + target: 'description', + actionType: 'overwrite', + }); + + mapping.set('comments', { + target: 'comments', + actionType: 'append', + }); + + mapping.set('summary', { + target: 'title', + actionType: 'nothing', + }); + + await api.pushToService({ + externalService, + mapping, + params: apiParams, + logger: mockedLogger, + }); + expect(externalService.updateIncident).toHaveBeenCalledWith({ + incidentId: 'incident-3', + incident: { + labels: ['kibana', 'elastic'], + priority: 'High', + issueType: '10006', + parent: null, + description: 'Incident description (updated at 2020-04-27T10:59:46.202Z by Elastic User)', + }, + }); + }); + + test('append & overwrite', async () => { + mapping.set('title', { + target: 'summary', + actionType: 'append', + }); + + mapping.set('description', { + target: 'description', + actionType: 'overwrite', + }); + + mapping.set('comments', { + target: 'comments', + actionType: 'append', + }); + + mapping.set('summary', { + target: 'title', + actionType: 'append', + }); + + await api.pushToService({ + externalService, + mapping, + params: apiParams, + logger: mockedLogger, + }); + expect(externalService.updateIncident).toHaveBeenCalledWith({ + incidentId: 'incident-3', + incident: { + labels: ['kibana', 'elastic'], + priority: 'High', + issueType: '10006', + parent: null, + summary: + 'title from jira \r\nIncident title (updated at 2020-04-27T10:59:46.202Z by Elastic User)', + description: 'Incident description (updated at 2020-04-27T10:59:46.202Z by Elastic User)', + }, + }); + }); + + test('append & nothing', async () => { + mapping.set('title', { + target: 'summary', + actionType: 'append', + }); + + mapping.set('description', { + target: 'description', + actionType: 'nothing', + }); + + mapping.set('comments', { + target: 'comments', + actionType: 'append', + }); + + mapping.set('summary', { + target: 'title', + actionType: 'append', + }); + + await api.pushToService({ + externalService, + mapping, + params: apiParams, + logger: mockedLogger, + }); + expect(externalService.updateIncident).toHaveBeenCalledWith({ + incidentId: 'incident-3', + incident: { + labels: ['kibana', 'elastic'], + priority: 'High', + issueType: '10006', + parent: null, + summary: + 'title from jira \r\nIncident title (updated at 2020-04-27T10:59:46.202Z by Elastic User)', + }, + }); + }); + + test('comment nothing', async () => { + mapping.set('title', { + target: 'summary', + actionType: 'overwrite', + }); + + mapping.set('description', { + target: 'description', + actionType: 'nothing', + }); + + mapping.set('comments', { + target: 'comments', + actionType: 'nothing', + }); + + mapping.set('summary', { + target: 'title', + actionType: 'overwrite', + }); + + await api.pushToService({ + externalService, + mapping, + params: apiParams, + logger: mockedLogger, }); + expect(externalService.createComment).not.toHaveBeenCalled(); }); }); }); diff --git a/x-pack/plugins/actions/server/builtin_action_types/jira/api.ts b/x-pack/plugins/actions/server/builtin_action_types/jira/api.ts index 679c1541964ce..feeb69b1d1a0e 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/jira/api.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/jira/api.ts @@ -17,6 +17,7 @@ import { PushToServiceApiParams, PushToServiceResponse, GetIssueHandlerArgs, + GetCommonFieldsHandlerArgs, } from './types'; // TODO: to remove, need to support Case @@ -39,6 +40,11 @@ const getIssueTypesHandler = async ({ externalService }: GetIssueTypesHandlerArg return res; }; +const getFieldsHandler = async ({ externalService }: GetCommonFieldsHandlerArgs) => { + const res = await externalService.getFields(); + return res; +}; + const getFieldsByIssueTypeHandler = async ({ externalService, params, @@ -157,6 +163,7 @@ const pushToServiceHandler = async ({ }; export const api: ExternalServiceApi = { + getFields: getFieldsHandler, handshake: handshakeHandler, pushToService: pushToServiceHandler, getIncident: getIncidentHandler, diff --git a/x-pack/plugins/actions/server/builtin_action_types/jira/index.ts b/x-pack/plugins/actions/server/builtin_action_types/jira/index.ts index 9d6ff90c33700..c70c0810926f4 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/jira/index.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/jira/index.ts @@ -40,6 +40,7 @@ interface GetActionTypeParams { } const supportedSubActions: string[] = [ + 'getFields', 'pushToService', 'issueTypes', 'fieldsByIssueType', @@ -145,6 +146,13 @@ async function executor( }); } + if (subAction === 'getFields') { + data = await api.getFields({ + externalService, + params: subActionParams, + }); + } + if (subAction === 'issues') { const getIssuesParams = subActionParams as ExecutorSubActionGetIssuesParams; data = await api.issues({ diff --git a/x-pack/plugins/actions/server/builtin_action_types/jira/mocks.ts b/x-pack/plugins/actions/server/builtin_action_types/jira/mocks.ts index b98eda799e3aa..87a0f156a0c2a 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/jira/mocks.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/jira/mocks.ts @@ -73,6 +73,20 @@ const createMock = (): jest.Mocked => { key: 'RJ-107', title: 'Test title', })), + getFields: jest.fn().mockImplementation(() => ({ + description: { + allowedValues: [], + defaultValue: {}, + required: true, + schema: { type: 'string' }, + }, + summary: { + allowedValues: [], + defaultValue: {}, + required: true, + schema: { type: 'string' }, + }, + })), }; service.createComment.mockImplementationOnce(() => @@ -97,7 +111,6 @@ const createMock = (): jest.Mocked => { const externalServiceMock = { create: createMock, }; - const mapping: Map> = new Map(); mapping.set('title', { diff --git a/x-pack/plugins/actions/server/builtin_action_types/jira/schema.ts b/x-pack/plugins/actions/server/builtin_action_types/jira/schema.ts index 513ca2cf18e6c..70b60ada9c386 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/jira/schema.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/jira/schema.ts @@ -55,6 +55,7 @@ export const ExecutorSubActionGetIncidentParamsSchema = schema.object({ }); // Reserved for future implementation +export const ExecutorSubActionCommonFieldsParamsSchema = schema.object({}); export const ExecutorSubActionHandshakeParamsSchema = schema.object({}); export const ExecutorSubActionGetCapabilitiesParamsSchema = schema.object({}); export const ExecutorSubActionGetIssueTypesParamsSchema = schema.object({}); @@ -65,6 +66,10 @@ export const ExecutorSubActionGetIssuesParamsSchema = schema.object({ title: sch export const ExecutorSubActionGetIssueParamsSchema = schema.object({ id: schema.string() }); export const ExecutorParamsSchema = schema.oneOf([ + schema.object({ + subAction: schema.literal('getFields'), + subActionParams: ExecutorSubActionCommonFieldsParamsSchema, + }), schema.object({ subAction: schema.literal('getIncident'), subActionParams: ExecutorSubActionGetIncidentParamsSchema, diff --git a/x-pack/plugins/actions/server/builtin_action_types/jira/service.test.ts b/x-pack/plugins/actions/server/builtin_action_types/jira/service.test.ts index fe4e135c76fc3..2165ba56428c9 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/jira/service.test.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/jira/service.test.ts @@ -57,8 +57,10 @@ const fieldsResponse = { id: '10006', name: 'Task', fields: { - summary: { fieldId: 'summary' }, + summary: { required: true, schema: { type: 'string' }, fieldId: 'summary' }, priority: { + required: false, + schema: { type: 'string' }, fieldId: 'priority', allowedValues: [ { @@ -198,7 +200,7 @@ describe('Jira service', () => { error.response = { data: { errors: { summary: 'Required field' } } }; throw error; }); - expect(service.getIncident('1')).rejects.toThrow( + await expect(service.getIncident('1')).rejects.toThrow( '[Action][Jira]: Unable to get incident with id 1. Error: An error has occurred Reason: Required field' ); }); @@ -348,7 +350,7 @@ describe('Jira service', () => { throw error; }); - expect( + await expect( service.createIncident({ incident: { summary: 'title', @@ -442,7 +444,7 @@ describe('Jira service', () => { throw error; }); - expect( + await expect( service.updateIncident({ incidentId: '1', incident: { @@ -526,7 +528,7 @@ describe('Jira service', () => { throw error; }); - expect( + await expect( service.createComment({ incidentId: '1', comment: { @@ -587,7 +589,7 @@ describe('Jira service', () => { throw error; }); - expect(service.getCapabilities()).rejects.toThrow( + await expect(service.getCapabilities()).rejects.toThrow( '[Action][Jira]: Unable to get capabilities. Error: An error has occurred. Reason: Could not get capabilities' ); }); @@ -657,7 +659,7 @@ describe('Jira service', () => { throw error; }); - expect(service.getIssueTypes()).rejects.toThrow( + await expect(service.getIssueTypes()).rejects.toThrow( '[Action][Jira]: Unable to get issue types. Error: An error has occurred. Reason: Could not get issue types' ); }); @@ -741,7 +743,7 @@ describe('Jira service', () => { throw error; }); - expect(service.getIssueTypes()).rejects.toThrow( + await expect(service.getIssueTypes()).rejects.toThrow( '[Action][Jira]: Unable to get issue types. Error: An error has occurred. Reason: Could not get issue types' ); }); @@ -765,6 +767,8 @@ describe('Jira service', () => { expect(res).toEqual({ priority: { + required: false, + schema: { type: 'string' }, allowedValues: [ { id: '1', name: 'Highest' }, { id: '2', name: 'High' }, @@ -774,7 +778,12 @@ describe('Jira service', () => { ], defaultValue: { id: '3', name: 'Medium' }, }, - summary: { allowedValues: [], defaultValue: {} }, + summary: { + required: true, + schema: { type: 'string' }, + allowedValues: [], + defaultValue: {}, + }, }); }); @@ -815,7 +824,7 @@ describe('Jira service', () => { throw error; }); - expect(service.getFieldsByIssueType('10006')).rejects.toThrow( + await expect(service.getFieldsByIssueType('10006')).rejects.toThrow( '[Action][Jira]: Unable to get fields. Error: An error has occurred. Reason: Could not get fields' ); }); @@ -837,8 +846,10 @@ describe('Jira service', () => { requestMock.mockImplementationOnce(() => ({ data: { values: [ - { fieldId: 'summary' }, + { required: true, schema: { type: 'string' }, fieldId: 'summary' }, { + required: false, + schema: { type: 'string' }, fieldId: 'priority', allowedValues: [ { @@ -859,10 +870,17 @@ describe('Jira service', () => { expect(res).toEqual({ priority: { + required: false, + schema: { type: 'string' }, allowedValues: [{ id: '3', name: 'Medium' }], defaultValue: { id: '3', name: 'Medium' }, }, - summary: { allowedValues: [], defaultValue: {} }, + summary: { + required: true, + schema: { type: 'string' }, + allowedValues: [], + defaultValue: {}, + }, }); }); @@ -881,8 +899,10 @@ describe('Jira service', () => { requestMock.mockImplementationOnce(() => ({ data: { values: [ - { fieldId: 'summary' }, + { required: true, schema: { type: 'string' }, fieldId: 'summary' }, { + required: true, + schema: { type: 'string' }, fieldId: 'priority', allowedValues: [ { @@ -927,7 +947,7 @@ describe('Jira service', () => { throw error; }); - expect(service.getFieldsByIssueType('10006')).rejects.toThrow( + await expect(service.getFieldsByIssueType('10006')).rejects.toThrowError( '[Action][Jira]: Unable to get fields. Error: An error has occurred. Reason: Could not get issue types' ); }); @@ -976,7 +996,7 @@ describe('Jira service', () => { throw error; }); - expect(service.getIssues('Test title')).rejects.toThrow( + await expect(service.getIssues('Test title')).rejects.toThrow( '[Action][Jira]: Unable to get issues. Error: An error has occurred. Reason: Could not get issue types' ); }); @@ -1020,9 +1040,128 @@ describe('Jira service', () => { throw error; }); - expect(service.getIssue('RJ-107')).rejects.toThrow( + await expect(service.getIssue('RJ-107')).rejects.toThrow( '[Action][Jira]: Unable to get issue with id RJ-107. Error: An error has occurred. Reason: Could not get issue types' ); }); }); + + describe('getFields', () => { + const callMocks = () => { + requestMock + .mockImplementationOnce(() => ({ + data: { + capabilities: { + 'list-project-issuetypes': + 'https://siem-kibana.atlassian.net/rest/capabilities/list-project-issuetypes', + 'list-issuetype-fields': + 'https://siem-kibana.atlassian.net/rest/capabilities/list-issuetype-fields', + }, + }, + })) + .mockImplementationOnce(() => ({ + data: { + values: issueTypesResponse.data.projects[0].issuetypes, + }, + })) + .mockImplementationOnce(() => ({ + data: { + capabilities: { + 'list-project-issuetypes': + 'https://siem-kibana.atlassian.net/rest/capabilities/list-project-issuetypes', + 'list-issuetype-fields': + 'https://siem-kibana.atlassian.net/rest/capabilities/list-issuetype-fields', + }, + }, + })) + .mockImplementationOnce(() => ({ + data: { + capabilities: { + 'list-project-issuetypes': + 'https://siem-kibana.atlassian.net/rest/capabilities/list-project-issuetypes', + 'list-issuetype-fields': + 'https://siem-kibana.atlassian.net/rest/capabilities/list-issuetype-fields', + }, + }, + })) + .mockImplementationOnce(() => ({ + data: { + values: [ + { required: true, schema: { type: 'string' }, fieldId: 'summary' }, + { required: true, schema: { type: 'string' }, fieldId: 'description' }, + { + required: false, + schema: { type: 'string' }, + fieldId: 'priority', + allowedValues: [ + { + name: 'Medium', + id: '3', + }, + ], + defaultValue: { + name: 'Medium', + id: '3', + }, + }, + ], + }, + })) + .mockImplementationOnce(() => ({ + data: { + values: [ + { required: true, schema: { type: 'string' }, fieldId: 'summary' }, + { required: true, schema: { type: 'string' }, fieldId: 'description' }, + ], + }, + })); + }; + beforeEach(() => { + jest.resetAllMocks(); + }); + test('it should call request with correct arguments', async () => { + callMocks(); + await service.getFields(); + const callUrls = [ + 'https://siem-kibana.atlassian.net/rest/capabilities', + 'https://siem-kibana.atlassian.net/rest/api/2/issue/createmeta/CK/issuetypes', + 'https://siem-kibana.atlassian.net/rest/capabilities', + 'https://siem-kibana.atlassian.net/rest/capabilities', + 'https://siem-kibana.atlassian.net/rest/api/2/issue/createmeta/CK/issuetypes/10006', + 'https://siem-kibana.atlassian.net/rest/api/2/issue/createmeta/CK/issuetypes/10007', + ]; + requestMock.mock.calls.forEach((call, i) => { + expect(call[0].url).toEqual(callUrls[i]); + }); + }); + test('it returns common fields correctly', async () => { + callMocks(); + const res = await service.getFields(); + expect(res).toEqual({ + description: { + allowedValues: [], + defaultValue: {}, + required: true, + schema: { type: 'string' }, + }, + summary: { + allowedValues: [], + defaultValue: {}, + required: true, + schema: { type: 'string' }, + }, + }); + }); + + test('it should throw an error', async () => { + requestMock.mockImplementation(() => { + const error: ResponseError = new Error('An error has occurred'); + error.response = { data: { errors: { summary: 'Required field' } } }; + throw error; + }); + await expect(service.getFields()).rejects.toThrow( + '[Action][Jira]: Unable to get capabilities. Error: An error has occurred. Reason: Required field' + ); + }); + }); }); diff --git a/x-pack/plugins/actions/server/builtin_action_types/jira/service.ts b/x-pack/plugins/actions/server/builtin_action_types/jira/service.ts index f5347891f4f70..b3c5bb4a84de5 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/jira/service.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/jira/service.ts @@ -8,18 +8,20 @@ import axios from 'axios'; import { Logger } from '../../../../../../src/core/server'; import { - ExternalServiceCredentials, - ExternalService, + CreateCommentParams, CreateIncidentParams, - UpdateIncidentParams, - JiraPublicConfigurationType, - JiraSecretConfigurationType, + ExternalService, + ExternalServiceCommentResponse, + ExternalServiceCredentials, + ExternalServiceIncidentResponse, Fields, - CreateCommentParams, + FieldSchema, + GetCommonFieldsResponse, Incident, + JiraPublicConfigurationType, + JiraSecretConfigurationType, ResponseError, - ExternalServiceCommentResponse, - ExternalServiceIncidentResponse, + UpdateIncidentParams, } from './types'; import * as i18n from './translations'; @@ -127,14 +129,21 @@ export const createExternalService = ( issueTypes.map((type) => ({ id: type.id, name: type.name })); const normalizeFields = (fields: { - [key: string]: { allowedValues?: Array<{}>; defaultValue?: {} }; + [key: string]: { + allowedValues?: Array<{}>; + defaultValue?: {}; + required: boolean; + schema: FieldSchema; + }; }) => Object.keys(fields ?? {}).reduce((fieldsAcc, fieldKey) => { return { ...fieldsAcc, [fieldKey]: { + required: fields[fieldKey]?.required, allowedValues: fields[fieldKey]?.allowedValues ?? [], defaultValue: fields[fieldKey]?.defaultValue ?? {}, + schema: fields[fieldKey]?.schema, }, }; }, {}); @@ -326,7 +335,6 @@ export const createExternalService = ( const getIssueTypes = async () => { const capabilitiesResponse = await getCapabilities(); const supportsNewAPI = hasSupportForNewAPI(capabilitiesResponse); - try { if (!supportsNewAPI) { const res = await request({ @@ -366,7 +374,6 @@ export const createExternalService = ( const getFieldsByIssueType = async (issueTypeId: string) => { const capabilitiesResponse = await getCapabilities(); const supportsNewAPI = hasSupportForNewAPI(capabilitiesResponse); - try { if (!supportsNewAPI) { const res = await request({ @@ -378,6 +385,7 @@ export const createExternalService = ( }); const fields = res.data.projects[0]?.issuetypes[0]?.fields || {}; + return normalizeFields(fields); } else { const res = await request({ @@ -409,6 +417,30 @@ export const createExternalService = ( } }; + const getFields = async () => { + try { + const issueTypes = await getIssueTypes(); + const fieldsPerIssueType = await Promise.all( + issueTypes.map((issueType) => getFieldsByIssueType(issueType.id)) + ); + return fieldsPerIssueType.reduce((acc: GetCommonFieldsResponse, fieldTypesByIssue) => { + const currentListOfFields = Object.keys(acc); + return currentListOfFields.length === 0 + ? fieldTypesByIssue + : currentListOfFields.reduce( + (add: GetCommonFieldsResponse, field) => + Object.keys(fieldTypesByIssue).includes(field) + ? { ...add, [field]: acc[field] } + : add, + {} + ); + }, {}); + } catch (error) { + // errors that happen here would be thrown in the contained async calls + throw error; + } + }; + const getIssues = async (title: string) => { const query = `${searchUrl}?jql=${encodeURIComponent( `project="${projectKey}" and summary ~"${title}"` @@ -461,6 +493,7 @@ export const createExternalService = ( }; return { + getFields, getIncident, createIncident, updateIncident, diff --git a/x-pack/plugins/actions/server/builtin_action_types/jira/types.ts b/x-pack/plugins/actions/server/builtin_action_types/jira/types.ts index 7d650a22fba1b..e142637010a98 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/jira/types.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/jira/types.ts @@ -79,11 +79,34 @@ export interface CreateCommentParams { comment: Comment; } +export interface FieldsSchema { + type: string; + [key: string]: string; +} + +export interface ExternalServiceFields { + clauseNames: string[]; + custom: boolean; + id: string; + key: string; + name: string; + navigatable: boolean; + orderable: boolean; + schema: FieldsSchema; + searchable: boolean; +} + export type GetIssueTypesResponse = Array<{ id: string; name: string }>; + +export interface FieldSchema { + type: string; + items?: string; +} export type GetFieldsByIssueTypeResponse = Record< string, - { allowedValues: Array<{}>; defaultValue: {} } + { allowedValues: Array<{}>; defaultValue: {}; required: boolean; schema: FieldSchema } >; +export type GetCommonFieldsResponse = GetFieldsByIssueTypeResponse; export type GetIssuesResponse = Array<{ id: string; key: string; title: string }>; export interface GetIssueResponse { @@ -93,15 +116,16 @@ export interface GetIssueResponse { } export interface ExternalService { - getIncident: (id: string) => Promise; - createIncident: (params: CreateIncidentParams) => Promise; - updateIncident: (params: UpdateIncidentParams) => Promise; createComment: (params: CreateCommentParams) => Promise; + createIncident: (params: CreateIncidentParams) => Promise; + getFields: () => Promise; getCapabilities: () => Promise; - getIssueTypes: () => Promise; getFieldsByIssueType: (issueTypeId: string) => Promise; - getIssues: (title: string) => Promise; + getIncident: (id: string) => Promise; getIssue: (id: string) => Promise; + getIssues: (title: string) => Promise; + getIssueTypes: () => Promise; + updateIncident: (params: UpdateIncidentParams) => Promise; } export interface PushToServiceApiParams extends ExecutorSubActionPushParams { @@ -157,6 +181,11 @@ export interface GetIssueTypesHandlerArgs { params: ExecutorSubActionGetIssueTypesParams; } +export interface GetCommonFieldsHandlerArgs { + externalService: ExternalService; + params: ExecutorSubActionGetIssueTypesParams; +} + export interface GetFieldsByIssueTypeHandlerArgs { externalService: ExternalService; params: ExecutorSubActionGetFieldsByIssueTypeParams; @@ -177,15 +206,16 @@ export interface GetIssueHandlerArgs { } export interface ExternalServiceApi { - handshake: (args: HandshakeApiHandlerArgs) => Promise; - pushToService: (args: PushToServiceApiHandlerArgs) => Promise; + getFields: (args: GetCommonFieldsHandlerArgs) => Promise; getIncident: (args: GetIncidentApiHandlerArgs) => Promise; + handshake: (args: HandshakeApiHandlerArgs) => Promise; issueTypes: (args: GetIssueTypesHandlerArgs) => Promise; + pushToService: (args: PushToServiceApiHandlerArgs) => Promise; fieldsByIssueType: ( args: GetFieldsByIssueTypeHandlerArgs ) => Promise; - issues: (args: GetIssuesHandlerArgs) => Promise; issue: (args: GetIssueHandlerArgs) => Promise; + issues: (args: GetIssuesHandlerArgs) => Promise; } export type JiraExecutorResultData = diff --git a/x-pack/plugins/actions/server/builtin_action_types/resilient/api.ts b/x-pack/plugins/actions/server/builtin_action_types/resilient/api.ts index 46d9c114297a9..29f2594d2b6f8 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/resilient/api.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/resilient/api.ts @@ -15,6 +15,7 @@ import { GetSeverityHandlerArgs, PushToServiceApiParams, PushToServiceResponse, + GetCommonFieldsHandlerArgs, } from './types'; // TODO: to remove, need to support Case @@ -32,6 +33,10 @@ const getIncidentHandler = async ({ params, }: GetIncidentApiHandlerArgs) => {}; +const getFieldsHandler = async ({ externalService }: GetCommonFieldsHandlerArgs) => { + const res = await externalService.getFields(); + return res; +}; const getIncidentTypesHandler = async ({ externalService }: GetIncidentTypesHandlerArgs) => { const res = await externalService.getIncidentTypes(); return res; @@ -136,9 +141,10 @@ const pushToServiceHandler = async ({ }; export const api: ExternalServiceApi = { - handshake: handshakeHandler, - pushToService: pushToServiceHandler, + getFields: getFieldsHandler, getIncident: getIncidentHandler, + handshake: handshakeHandler, incidentTypes: getIncidentTypesHandler, + pushToService: pushToServiceHandler, severity: getSeverityHandler, }; diff --git a/x-pack/plugins/actions/server/builtin_action_types/resilient/index.ts b/x-pack/plugins/actions/server/builtin_action_types/resilient/index.ts index 53285a2a350af..6203dda4120f5 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/resilient/index.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/resilient/index.ts @@ -25,6 +25,7 @@ import { ResilientExecutorResultData, ExecutorSubActionGetIncidentTypesParams, ExecutorSubActionGetSeverityParams, + ExecutorSubActionCommonFieldsParams, } from './types'; import * as i18n from './translations'; import { Logger } from '../../../../../../src/core/server'; @@ -37,7 +38,7 @@ interface GetActionTypeParams { configurationUtilities: ActionsConfigurationUtilities; } -const supportedSubActions: string[] = ['pushToService', 'incidentTypes', 'severity']; +const supportedSubActions: string[] = ['getFields', 'pushToService', 'incidentTypes', 'severity']; // action type definition export function getActionType( @@ -122,6 +123,14 @@ async function executor( logger.debug(`response push to service for incident id: ${data.id}`); } + if (subAction === 'getFields') { + const getFieldsParams = subActionParams as ExecutorSubActionCommonFieldsParams; + data = await api.getFields({ + externalService, + params: getFieldsParams, + }); + } + if (subAction === 'incidentTypes') { const incidentTypesParams = subActionParams as ExecutorSubActionGetIncidentTypesParams; data = await api.incidentTypes({ diff --git a/x-pack/plugins/actions/server/builtin_action_types/resilient/mocks.ts b/x-pack/plugins/actions/server/builtin_action_types/resilient/mocks.ts index 2e841728159a3..2b2a22a66b709 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/resilient/mocks.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/resilient/mocks.ts @@ -8,8 +8,275 @@ import { ExternalService, PushToServiceApiParams, ExecutorSubActionPushParams } import { MapRecord } from '../case/types'; +export const resilientFields = [ + { + id: 17, + name: 'name', + text: 'Name', + prefix: null, + type_id: 0, + tooltip: 'A unique name to identify this particular incident.', + input_type: 'text', + required: 'always', + hide_notification: false, + chosen: false, + default_chosen_by_server: false, + blank_option: false, + internal: true, + uuid: 'ad6ed4f2-8d87-4ba2-81fa-03568a9326cc', + operations: [ + 'equals', + 'not_equals', + 'contains', + 'not_contains', + 'changed', + 'changed_to', + 'not_changed_to', + 'has_a_value', + 'not_has_a_value', + ], + operation_perms: { + changed_to: { + show_in_manual_actions: false, + show_in_auto_actions: true, + show_in_notifications: true, + }, + has_a_value: { + show_in_manual_actions: true, + show_in_auto_actions: true, + show_in_notifications: true, + }, + not_changed_to: { + show_in_manual_actions: false, + show_in_auto_actions: true, + show_in_notifications: true, + }, + equals: { + show_in_manual_actions: true, + show_in_auto_actions: true, + show_in_notifications: true, + }, + changed: { + show_in_manual_actions: false, + show_in_auto_actions: true, + show_in_notifications: true, + }, + contains: { + show_in_manual_actions: true, + show_in_auto_actions: true, + show_in_notifications: true, + }, + not_contains: { + show_in_manual_actions: true, + show_in_auto_actions: true, + show_in_notifications: true, + }, + not_equals: { + show_in_manual_actions: true, + show_in_auto_actions: true, + show_in_notifications: true, + }, + not_has_a_value: { + show_in_manual_actions: true, + show_in_auto_actions: true, + show_in_notifications: true, + }, + }, + values: [], + perms: { + delete: false, + modify_name: false, + modify_values: false, + modify_blank: false, + modify_required: false, + modify_operations: false, + modify_chosen: false, + modify_default: false, + show_in_manual_actions: true, + show_in_auto_actions: true, + show_in_notifications: true, + show_in_scripts: true, + modify_type: ['text'], + sort: true, + }, + read_only: false, + changeable: true, + rich_text: false, + templates: [], + deprecated: false, + tags: [], + calculated: false, + is_tracked: false, + allow_default_value: false, + }, + { + id: 15, + name: 'description', + text: 'Description', + prefix: null, + type_id: 0, + tooltip: 'A free form text description of the incident.', + input_type: 'textarea', + hide_notification: false, + chosen: false, + default_chosen_by_server: false, + blank_option: false, + internal: true, + uuid: '420d70b1-98f9-4681-a20b-84f36a9e5e48', + operations: [ + 'equals', + 'not_equals', + 'contains', + 'not_contains', + 'changed', + 'changed_to', + 'not_changed_to', + 'has_a_value', + 'not_has_a_value', + ], + operation_perms: { + changed_to: { + show_in_manual_actions: false, + show_in_auto_actions: true, + show_in_notifications: true, + }, + has_a_value: { + show_in_manual_actions: true, + show_in_auto_actions: true, + show_in_notifications: true, + }, + not_changed_to: { + show_in_manual_actions: false, + show_in_auto_actions: true, + show_in_notifications: true, + }, + equals: { + show_in_manual_actions: true, + show_in_auto_actions: true, + show_in_notifications: true, + }, + changed: { + show_in_manual_actions: false, + show_in_auto_actions: true, + show_in_notifications: true, + }, + contains: { + show_in_manual_actions: true, + show_in_auto_actions: true, + show_in_notifications: true, + }, + not_contains: { + show_in_manual_actions: true, + show_in_auto_actions: true, + show_in_notifications: true, + }, + not_equals: { + show_in_manual_actions: true, + show_in_auto_actions: true, + show_in_notifications: true, + }, + not_has_a_value: { + show_in_manual_actions: true, + show_in_auto_actions: true, + show_in_notifications: true, + }, + }, + values: [], + perms: { + delete: false, + modify_name: false, + modify_values: false, + modify_blank: false, + modify_required: false, + modify_operations: false, + modify_chosen: false, + modify_default: false, + show_in_manual_actions: true, + show_in_auto_actions: true, + show_in_notifications: true, + show_in_scripts: true, + modify_type: ['textarea'], + sort: true, + }, + read_only: false, + changeable: true, + rich_text: true, + templates: [], + deprecated: false, + tags: [], + calculated: false, + is_tracked: false, + allow_default_value: false, + }, + { + id: 65, + name: 'create_date', + text: 'Date Created', + prefix: null, + type_id: 0, + tooltip: 'The date the incident was created. This field is read-only.', + input_type: 'datetimepicker', + hide_notification: false, + chosen: false, + default_chosen_by_server: false, + blank_option: false, + internal: true, + uuid: 'b4faf728-881a-4e8b-bf0b-d39b720392a1', + operations: ['due_within', 'overdue_by', 'has_a_value', 'not_has_a_value'], + operation_perms: { + has_a_value: { + show_in_manual_actions: true, + show_in_auto_actions: true, + show_in_notifications: true, + }, + not_has_a_value: { + show_in_manual_actions: true, + show_in_auto_actions: true, + show_in_notifications: true, + }, + due_within: { + show_in_manual_actions: true, + show_in_auto_actions: true, + show_in_notifications: true, + }, + overdue_by: { + show_in_manual_actions: true, + show_in_auto_actions: true, + show_in_notifications: true, + }, + }, + values: [], + perms: { + delete: false, + modify_name: false, + modify_values: false, + modify_blank: false, + modify_required: false, + modify_operations: false, + modify_chosen: false, + modify_default: false, + show_in_manual_actions: true, + show_in_auto_actions: true, + show_in_notifications: true, + show_in_scripts: true, + modify_type: ['datetimepicker'], + sort: true, + }, + read_only: true, + changeable: false, + rich_text: false, + templates: [], + deprecated: false, + tags: [], + calculated: false, + is_tracked: false, + allow_default_value: false, + }, +]; + const createMock = (): jest.Mocked => { const service = { + getFields: jest.fn().mockImplementation(() => Promise.resolve(resilientFields)), getIncident: jest.fn().mockImplementation(() => Promise.resolve({ id: '1', diff --git a/x-pack/plugins/actions/server/builtin_action_types/resilient/schema.ts b/x-pack/plugins/actions/server/builtin_action_types/resilient/schema.ts index b6e3a9525dfd4..c7ceba94140fb 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/resilient/schema.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/resilient/schema.ts @@ -53,11 +53,16 @@ export const ExecutorSubActionGetIncidentParamsSchema = schema.object({ }); // Reserved for future implementation +export const ExecutorSubActionCommonFieldsParamsSchema = schema.object({}); export const ExecutorSubActionHandshakeParamsSchema = schema.object({}); export const ExecutorSubActionGetIncidentTypesParamsSchema = schema.object({}); export const ExecutorSubActionGetSeverityParamsSchema = schema.object({}); export const ExecutorParamsSchema = schema.oneOf([ + schema.object({ + subAction: schema.literal('getFields'), + subActionParams: ExecutorSubActionCommonFieldsParamsSchema, + }), schema.object({ subAction: schema.literal('getIncident'), subActionParams: ExecutorSubActionGetIncidentParamsSchema, diff --git a/x-pack/plugins/actions/server/builtin_action_types/resilient/service.test.ts b/x-pack/plugins/actions/server/builtin_action_types/resilient/service.test.ts index 86ea352625a5b..ecf246cb8fe3c 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/resilient/service.test.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/resilient/service.test.ts @@ -11,7 +11,7 @@ import * as utils from '../lib/axios_utils'; import { ExternalService } from './types'; import { Logger } from '../../../../../../src/core/server'; import { loggingSystemMock } from '../../../../../../src/core/server/mocks'; -import { incidentTypes, severity } from './mocks'; +import { incidentTypes, resilientFields, severity } from './mocks'; const logger = loggingSystemMock.create().get() as jest.Mocked; @@ -231,7 +231,7 @@ describe('IBM Resilient service', () => { requestMock.mockImplementation(() => { throw new Error('An error has occurred'); }); - expect(service.getIncident('1')).rejects.toThrow( + await expect(service.getIncident('1')).rejects.toThrow( 'Unable to get incident with id 1. Error: An error has occurred' ); }); @@ -310,7 +310,7 @@ describe('IBM Resilient service', () => { throw new Error('An error has occurred'); }); - expect( + await expect( service.createIncident({ incident: { name: 'title', @@ -418,7 +418,7 @@ describe('IBM Resilient service', () => { test('it should throw an error', async () => { mockIncidentUpdate(true); - expect( + await expect( service.updateIncident({ incidentId: '1', incident: { @@ -502,7 +502,7 @@ describe('IBM Resilient service', () => { throw new Error('An error has occurred'); }); - expect( + await expect( service.createComment({ incidentId: '1', comment: { @@ -541,7 +541,7 @@ describe('IBM Resilient service', () => { throw new Error('An error has occurred'); }); - expect(service.getIncidentTypes()).rejects.toThrow( + await expect(service.getIncidentTypes()).rejects.toThrow( '[Action][IBM Resilient]: Unable to get incident types. Error: An error has occurred.' ); }); @@ -578,9 +578,40 @@ describe('IBM Resilient service', () => { throw new Error('An error has occurred'); }); - expect(service.getIncidentTypes()).rejects.toThrow( + await expect(service.getIncidentTypes()).rejects.toThrow( '[Action][IBM Resilient]: Unable to get incident types. Error: An error has occurred.' ); }); }); + + describe('getFields', () => { + test('it should call request with correct arguments', async () => { + requestMock.mockImplementation(() => ({ + data: resilientFields, + })); + await service.getFields(); + + expect(requestMock).toHaveBeenCalledWith({ + axios, + logger, + url: 'https://resilient.elastic.co/rest/orgs/201/types/incident/fields', + }); + }); + test('it returns common fields correctly', async () => { + requestMock.mockImplementation(() => ({ + data: resilientFields, + })); + const res = await service.getFields(); + expect(res).toEqual(resilientFields); + }); + + test('it should throw an error', async () => { + requestMock.mockImplementation(() => { + throw new Error('An error has occurred'); + }); + await expect(service.getFields()).rejects.toThrow( + 'Unable to get fields. Error: An error has occurred' + ); + }); + }); }); diff --git a/x-pack/plugins/actions/server/builtin_action_types/resilient/service.ts b/x-pack/plugins/actions/server/builtin_action_types/resilient/service.ts index 4bf1453641e42..a13204f8bb1d8 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/resilient/service.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/resilient/service.ts @@ -303,12 +303,27 @@ export const createExternalService = ( } }; + const getFields = async () => { + try { + const res = await request({ + axios: axiosInstance, + url: incidentFieldsUrl, + logger, + proxySettings, + }); + return res.data ?? []; + } catch (error) { + throw new Error(getErrorMessage(i18n.NAME, `Unable to get fields. Error: ${error.message}.`)); + } + }; + return { - getIncident, - createIncident, - updateIncident, createComment, + createIncident, + getFields, + getIncident, getIncidentTypes, getSeverity, + updateIncident, }; }; diff --git a/x-pack/plugins/actions/server/builtin_action_types/resilient/types.ts b/x-pack/plugins/actions/server/builtin_action_types/resilient/types.ts index ed622ee473b65..a70420b30a092 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/resilient/types.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/resilient/types.ts @@ -8,14 +8,15 @@ import { TypeOf } from '@kbn/config-schema'; import { - ExternalIncidentServiceConfigurationSchema, - ExternalIncidentServiceSecretConfigurationSchema, ExecutorParamsSchema, - ExecutorSubActionPushParamsSchema, + ExecutorSubActionCommonFieldsParamsSchema, ExecutorSubActionGetIncidentParamsSchema, - ExecutorSubActionHandshakeParamsSchema, ExecutorSubActionGetIncidentTypesParamsSchema, ExecutorSubActionGetSeverityParamsSchema, + ExecutorSubActionHandshakeParamsSchema, + ExecutorSubActionPushParamsSchema, + ExternalIncidentServiceConfigurationSchema, + ExternalIncidentServiceSecretConfigurationSchema, } from './schema'; import { ActionsConfigurationUtilities } from '../../actions_config'; @@ -31,6 +32,10 @@ export type ResilientSecretConfigurationType = TypeOf< typeof ExternalIncidentServiceSecretConfigurationSchema >; +export type ExecutorSubActionCommonFieldsParams = TypeOf< + typeof ExecutorSubActionCommonFieldsParamsSchema +>; + export type ExecutorParams = TypeOf; export type ExecutorSubActionPushParams = TypeOf; @@ -60,6 +65,14 @@ export interface ExternalServiceCommentResponse { } export type ExternalServiceParams = Record; +export interface ExternalServiceFields { + id: string; + input_type: string; + name: string; + read_only: boolean; + required?: string; +} +export type GetCommonFieldsResponse = ExternalServiceFields[]; export type Incident = Pick< ExecutorSubActionPushParams, @@ -86,12 +99,13 @@ export type GetIncidentTypesResponse = Array<{ id: string; name: string }>; export type GetSeverityResponse = Array<{ id: string; name: string }>; export interface ExternalService { - getIncident: (id: string) => Promise; - createIncident: (params: CreateIncidentParams) => Promise; - updateIncident: (params: UpdateIncidentParams) => Promise; createComment: (params: CreateCommentParams) => Promise; + createIncident: (params: CreateIncidentParams) => Promise; + getFields: () => Promise; + getIncident: (id: string) => Promise; getIncidentTypes: () => Promise; getSeverity: () => Promise; + updateIncident: (params: UpdateIncidentParams) => Promise; } export interface PushToServiceApiParams extends ExecutorSubActionPushParams { @@ -132,6 +146,11 @@ export interface HandshakeApiHandlerArgs extends ExternalServiceApiHandlerArgs { params: ExecutorSubActionHandshakeParams; } +export interface GetCommonFieldsHandlerArgs { + externalService: ExternalService; + params: ExecutorSubActionCommonFieldsParams; +} + export interface GetIncidentTypesHandlerArgs { externalService: ExternalService; params: ExecutorSubActionGetIncidentTypesParams; @@ -147,6 +166,7 @@ export interface PushToServiceResponse extends ExternalServiceIncidentResponse { } export interface ExternalServiceApi { + getFields: (args: GetCommonFieldsHandlerArgs) => Promise; handshake: (args: HandshakeApiHandlerArgs) => Promise; pushToService: (args: PushToServiceApiHandlerArgs) => Promise; getIncident: (args: GetIncidentApiHandlerArgs) => Promise; @@ -156,6 +176,7 @@ export interface ExternalServiceApi { export type ResilientExecutorResultData = | PushToServiceResponse + | GetCommonFieldsResponse | GetIncidentTypesResponse | GetSeverityResponse; diff --git a/x-pack/plugins/actions/server/builtin_action_types/servicenow/api.test.ts b/x-pack/plugins/actions/server/builtin_action_types/servicenow/api.test.ts index d49c2f265d04f..4683b661e21da 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/servicenow/api.test.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/servicenow/api.test.ts @@ -5,7 +5,7 @@ */ import { Logger } from '../../../../../../src/core/server'; -import { externalServiceMock, mapping, apiParams } from './mocks'; +import { externalServiceMock, mapping, apiParams, serviceNowCommonFields } from './mocks'; import { ExternalService } from './types'; import { api } from './api'; let mockedLogger: jest.Mocked; @@ -15,634 +15,619 @@ describe('api', () => { beforeEach(() => { externalService = externalServiceMock.create(); - jest.clearAllMocks(); }); - afterEach(() => { - jest.clearAllMocks(); - }); + describe('create incident', () => { + test('it creates an incident', async () => { + const params = { ...apiParams, externalId: null }; + const res = await api.pushToService({ + externalService, + mapping, + params, + secrets: {}, + logger: mockedLogger, + }); - describe('pushToService', () => { - describe('create incident', () => { - test('it creates an incident', async () => { - const params = { ...apiParams, externalId: null }; - const res = await api.pushToService({ - externalService, - mapping, - params, - secrets: {}, - logger: mockedLogger, - }); - - expect(res).toEqual({ - id: 'incident-1', - title: 'INC01', - pushedDate: '2020-03-10T12:24:20.000Z', - url: 'https://instance.service-now.com/nav_to.do?uri=incident.do?sys_id=123', - comments: [ - { - commentId: 'case-comment-1', - pushedDate: '2020-03-10T12:24:20.000Z', - }, - { - commentId: 'case-comment-2', - pushedDate: '2020-03-10T12:24:20.000Z', - }, - ], - }); - }); - - test('it creates an incident without comments', async () => { - const params = { ...apiParams, externalId: null, comments: [] }; - const res = await api.pushToService({ - externalService, - mapping, - params, - secrets: {}, - logger: mockedLogger, - }); - - expect(res).toEqual({ - id: 'incident-1', - title: 'INC01', - pushedDate: '2020-03-10T12:24:20.000Z', - url: 'https://instance.service-now.com/nav_to.do?uri=incident.do?sys_id=123', - }); - }); - - test('it calls createIncident correctly', async () => { - const params = { ...apiParams, externalId: null, comments: [] }; - await api.pushToService({ - externalService, - mapping, - params, - secrets: { username: 'elastic', password: 'elastic' }, - logger: mockedLogger, - }); - - expect(externalService.createIncident).toHaveBeenCalledWith({ - incident: { - severity: '1', - urgency: '2', - impact: '3', - caller_id: 'elastic', - description: - 'Incident description (created at 2020-03-13T08:34:53.450Z by Elastic User)', - short_description: - 'Incident title (created at 2020-03-13T08:34:53.450Z by Elastic User)', - }, - }); - expect(externalService.updateIncident).not.toHaveBeenCalled(); - }); - - test('it calls updateIncident correctly when creating an incident and having comments', async () => { - const params = { ...apiParams, externalId: null }; - await api.pushToService({ - externalService, - mapping, - params, - secrets: {}, - logger: mockedLogger, - }); - expect(externalService.updateIncident).toHaveBeenCalledTimes(2); - expect(externalService.updateIncident).toHaveBeenNthCalledWith(1, { - incident: { - severity: '1', - urgency: '2', - impact: '3', - comments: 'A comment (added at 2020-03-13T08:34:53.450Z by Elastic User)', - description: - 'Incident description (created at 2020-03-13T08:34:53.450Z by Elastic User)', - short_description: - 'Incident title (created at 2020-03-13T08:34:53.450Z by Elastic User)', + expect(res).toEqual({ + id: 'incident-1', + title: 'INC01', + pushedDate: '2020-03-10T12:24:20.000Z', + url: 'https://instance.service-now.com/nav_to.do?uri=incident.do?sys_id=123', + comments: [ + { + commentId: 'case-comment-1', + pushedDate: '2020-03-10T12:24:20.000Z', }, - incidentId: 'incident-1', - }); - - expect(externalService.updateIncident).toHaveBeenNthCalledWith(2, { - incident: { - severity: '1', - urgency: '2', - impact: '3', - comments: 'Another comment (added at 2020-03-13T08:34:53.450Z by Elastic User)', - description: - 'Incident description (created at 2020-03-13T08:34:53.450Z by Elastic User)', - short_description: - 'Incident title (created at 2020-03-13T08:34:53.450Z by Elastic User)', + { + commentId: 'case-comment-2', + pushedDate: '2020-03-10T12:24:20.000Z', }, - incidentId: 'incident-1', - }); + ], }); }); - describe('update incident', () => { - test('it updates an incident', async () => { - const res = await api.pushToService({ - externalService, - mapping, - params: apiParams, - secrets: {}, - logger: mockedLogger, - }); - - expect(res).toEqual({ - id: 'incident-2', - title: 'INC02', - pushedDate: '2020-03-10T12:24:20.000Z', - url: 'https://instance.service-now.com/nav_to.do?uri=incident.do?sys_id=123', - comments: [ - { - commentId: 'case-comment-1', - pushedDate: '2020-03-10T12:24:20.000Z', - }, - { - commentId: 'case-comment-2', - pushedDate: '2020-03-10T12:24:20.000Z', - }, - ], - }); - }); - - test('it updates an incident without comments', async () => { - const params = { ...apiParams, comments: [] }; - const res = await api.pushToService({ - externalService, - mapping, - params, - secrets: {}, - logger: mockedLogger, - }); - - expect(res).toEqual({ - id: 'incident-2', - title: 'INC02', - pushedDate: '2020-03-10T12:24:20.000Z', - url: 'https://instance.service-now.com/nav_to.do?uri=incident.do?sys_id=123', - }); - }); - - test('it calls updateIncident correctly', async () => { - const params = { ...apiParams }; - await api.pushToService({ - externalService, - mapping, - params, - secrets: {}, - logger: mockedLogger, - }); - - expect(externalService.updateIncident).toHaveBeenCalledWith({ - incidentId: 'incident-3', - incident: { - severity: '1', - urgency: '2', - impact: '3', - description: - 'Incident description (updated at 2020-03-13T08:34:53.450Z by Elastic User)', - short_description: - 'Incident title (updated at 2020-03-13T08:34:53.450Z by Elastic User)', - }, - }); - expect(externalService.createIncident).not.toHaveBeenCalled(); - }); - - test('it calls updateIncident to create a comments correctly', async () => { - const params = { ...apiParams }; - await api.pushToService({ - externalService, - mapping, - params, - secrets: {}, - logger: mockedLogger, - }); - expect(externalService.updateIncident).toHaveBeenCalledTimes(3); - expect(externalService.updateIncident).toHaveBeenNthCalledWith(1, { - incident: { - severity: '1', - urgency: '2', - impact: '3', - description: - 'Incident description (updated at 2020-03-13T08:34:53.450Z by Elastic User)', - short_description: - 'Incident title (updated at 2020-03-13T08:34:53.450Z by Elastic User)', - }, - incidentId: 'incident-3', - }); - - expect(externalService.updateIncident).toHaveBeenNthCalledWith(2, { - incident: { - severity: '1', - urgency: '2', - impact: '3', - comments: 'A comment (added at 2020-03-13T08:34:53.450Z by Elastic User)', - description: - 'Incident description (updated at 2020-03-13T08:34:53.450Z by Elastic User)', - short_description: - 'Incident title (updated at 2020-03-13T08:34:53.450Z by Elastic User)', - }, - incidentId: 'incident-2', - }); + test('it creates an incident without comments', async () => { + const params = { ...apiParams, externalId: null, comments: [] }; + const res = await api.pushToService({ + externalService, + mapping, + params, + secrets: {}, + logger: mockedLogger, + }); + + expect(res).toEqual({ + id: 'incident-1', + title: 'INC01', + pushedDate: '2020-03-10T12:24:20.000Z', + url: 'https://instance.service-now.com/nav_to.do?uri=incident.do?sys_id=123', }); }); - describe('mapping variations', () => { - test('overwrite & append', async () => { - mapping.set('title', { - target: 'short_description', - actionType: 'overwrite', - }); - - mapping.set('description', { - target: 'description', - actionType: 'append', - }); - - mapping.set('comments', { - target: 'comments', - actionType: 'append', - }); - - mapping.set('short_description', { - target: 'title', - actionType: 'overwrite', - }); - - await api.pushToService({ - externalService, - mapping, - params: apiParams, - secrets: {}, - logger: mockedLogger, - }); - expect(externalService.updateIncident).toHaveBeenCalledWith({ - incidentId: 'incident-3', - incident: { - severity: '1', - urgency: '2', - impact: '3', - short_description: - 'Incident title (updated at 2020-03-13T08:34:53.450Z by Elastic User)', - description: - 'description from servicenow \r\nIncident description (updated at 2020-03-13T08:34:53.450Z by Elastic User)', - }, - }); - }); - - test('nothing & append', async () => { - mapping.set('title', { - target: 'short_description', - actionType: 'nothing', - }); - - mapping.set('description', { - target: 'description', - actionType: 'append', - }); - - mapping.set('comments', { - target: 'comments', - actionType: 'append', - }); - - mapping.set('short_description', { - target: 'title', - actionType: 'nothing', - }); - - await api.pushToService({ - externalService, - mapping, - params: apiParams, - secrets: {}, - logger: mockedLogger, - }); - expect(externalService.updateIncident).toHaveBeenCalledWith({ - incidentId: 'incident-3', - incident: { - severity: '1', - urgency: '2', - impact: '3', - description: - 'description from servicenow \r\nIncident description (updated at 2020-03-13T08:34:53.450Z by Elastic User)', - }, - }); - }); - - test('append & append', async () => { - mapping.set('title', { - target: 'short_description', - actionType: 'append', - }); - - mapping.set('description', { - target: 'description', - actionType: 'append', - }); - - mapping.set('comments', { - target: 'comments', - actionType: 'append', - }); - - mapping.set('short_description', { - target: 'title', - actionType: 'append', - }); - - await api.pushToService({ - externalService, - mapping, - params: apiParams, - secrets: {}, - logger: mockedLogger, - }); - expect(externalService.updateIncident).toHaveBeenCalledWith({ - incidentId: 'incident-3', - incident: { - severity: '1', - urgency: '2', - impact: '3', - short_description: - 'title from servicenow \r\nIncident title (updated at 2020-03-13T08:34:53.450Z by Elastic User)', - description: - 'description from servicenow \r\nIncident description (updated at 2020-03-13T08:34:53.450Z by Elastic User)', - }, - }); - }); - - test('nothing & nothing', async () => { - mapping.set('title', { - target: 'short_description', - actionType: 'nothing', - }); - - mapping.set('description', { - target: 'description', - actionType: 'nothing', - }); - - mapping.set('comments', { - target: 'comments', - actionType: 'append', - }); - - mapping.set('short_description', { - target: 'title', - actionType: 'nothing', - }); - - await api.pushToService({ - externalService, - mapping, - params: apiParams, - secrets: {}, - logger: mockedLogger, - }); - - expect(externalService.updateIncident).toHaveBeenCalledWith({ - incidentId: 'incident-3', - incident: { - severity: '1', - urgency: '2', - impact: '3', - }, - }); - }); - - test('overwrite & nothing', async () => { - mapping.set('title', { - target: 'short_description', - actionType: 'overwrite', - }); - - mapping.set('description', { - target: 'description', - actionType: 'nothing', - }); - - mapping.set('comments', { - target: 'comments', - actionType: 'append', - }); - - mapping.set('short_description', { - target: 'title', - actionType: 'overwrite', - }); - - await api.pushToService({ - externalService, - mapping, - params: apiParams, - secrets: {}, - logger: mockedLogger, - }); - expect(externalService.updateIncident).toHaveBeenCalledWith({ - incidentId: 'incident-3', - incident: { - severity: '1', - urgency: '2', - impact: '3', - short_description: - 'Incident title (updated at 2020-03-13T08:34:53.450Z by Elastic User)', - }, - }); - }); - - test('overwrite & overwrite', async () => { - mapping.set('title', { - target: 'short_description', - actionType: 'overwrite', - }); - - mapping.set('description', { - target: 'description', - actionType: 'overwrite', - }); - - mapping.set('comments', { - target: 'comments', - actionType: 'append', - }); - - mapping.set('short_description', { - target: 'title', - actionType: 'overwrite', - }); - - await api.pushToService({ - externalService, - mapping, - params: apiParams, - secrets: {}, - logger: mockedLogger, - }); - expect(externalService.updateIncident).toHaveBeenCalledWith({ - incidentId: 'incident-3', - incident: { - severity: '1', - urgency: '2', - impact: '3', - short_description: - 'Incident title (updated at 2020-03-13T08:34:53.450Z by Elastic User)', - description: - 'Incident description (updated at 2020-03-13T08:34:53.450Z by Elastic User)', - }, - }); - }); - - test('nothing & overwrite', async () => { - mapping.set('title', { - target: 'short_description', - actionType: 'nothing', - }); - - mapping.set('description', { - target: 'description', - actionType: 'overwrite', - }); - - mapping.set('comments', { - target: 'comments', - actionType: 'append', - }); - - mapping.set('short_description', { - target: 'title', - actionType: 'nothing', - }); - - await api.pushToService({ - externalService, - mapping, - params: apiParams, - secrets: {}, - logger: mockedLogger, - }); - expect(externalService.updateIncident).toHaveBeenCalledWith({ - incidentId: 'incident-3', - incident: { - severity: '1', - urgency: '2', - impact: '3', - description: - 'Incident description (updated at 2020-03-13T08:34:53.450Z by Elastic User)', - }, - }); - }); - - test('append & overwrite', async () => { - mapping.set('title', { - target: 'short_description', - actionType: 'append', - }); - - mapping.set('description', { - target: 'description', - actionType: 'overwrite', - }); - - mapping.set('comments', { - target: 'comments', - actionType: 'append', - }); - - mapping.set('short_description', { - target: 'title', - actionType: 'append', - }); - - await api.pushToService({ - externalService, - mapping, - params: apiParams, - secrets: {}, - logger: mockedLogger, - }); - expect(externalService.updateIncident).toHaveBeenCalledWith({ - incidentId: 'incident-3', - incident: { - severity: '1', - urgency: '2', - impact: '3', - short_description: - 'title from servicenow \r\nIncident title (updated at 2020-03-13T08:34:53.450Z by Elastic User)', - description: - 'Incident description (updated at 2020-03-13T08:34:53.450Z by Elastic User)', + test('it calls createIncident correctly', async () => { + const params = { ...apiParams, externalId: null, comments: [] }; + await api.pushToService({ + externalService, + mapping, + params, + secrets: { username: 'elastic', password: 'elastic' }, + logger: mockedLogger, + }); + + expect(externalService.createIncident).toHaveBeenCalledWith({ + incident: { + severity: '1', + urgency: '2', + impact: '3', + caller_id: 'elastic', + description: 'Incident description (created at 2020-03-13T08:34:53.450Z by Elastic User)', + short_description: 'Incident title (created at 2020-03-13T08:34:53.450Z by Elastic User)', + }, + }); + expect(externalService.updateIncident).not.toHaveBeenCalled(); + }); + + test('it calls updateIncident correctly when creating an incident and having comments', async () => { + const params = { ...apiParams, externalId: null }; + await api.pushToService({ + externalService, + mapping, + params, + secrets: {}, + logger: mockedLogger, + }); + expect(externalService.updateIncident).toHaveBeenCalledTimes(2); + expect(externalService.updateIncident).toHaveBeenNthCalledWith(1, { + incident: { + severity: '1', + urgency: '2', + impact: '3', + comments: 'A comment (added at 2020-03-13T08:34:53.450Z by Elastic User)', + description: 'Incident description (created at 2020-03-13T08:34:53.450Z by Elastic User)', + short_description: 'Incident title (created at 2020-03-13T08:34:53.450Z by Elastic User)', + }, + incidentId: 'incident-1', + }); + + expect(externalService.updateIncident).toHaveBeenNthCalledWith(2, { + incident: { + severity: '1', + urgency: '2', + impact: '3', + comments: 'Another comment (added at 2020-03-13T08:34:53.450Z by Elastic User)', + description: 'Incident description (created at 2020-03-13T08:34:53.450Z by Elastic User)', + short_description: 'Incident title (created at 2020-03-13T08:34:53.450Z by Elastic User)', + }, + incidentId: 'incident-1', + }); + }); + }); + + describe('update incident', () => { + test('it updates an incident', async () => { + const res = await api.pushToService({ + externalService, + mapping, + params: apiParams, + secrets: {}, + logger: mockedLogger, + }); + + expect(res).toEqual({ + id: 'incident-2', + title: 'INC02', + pushedDate: '2020-03-10T12:24:20.000Z', + url: 'https://instance.service-now.com/nav_to.do?uri=incident.do?sys_id=123', + comments: [ + { + commentId: 'case-comment-1', + pushedDate: '2020-03-10T12:24:20.000Z', }, - }); - }); - - test('append & nothing', async () => { - mapping.set('title', { - target: 'short_description', - actionType: 'append', - }); - - mapping.set('description', { - target: 'description', - actionType: 'nothing', - }); - - mapping.set('comments', { - target: 'comments', - actionType: 'append', - }); - - mapping.set('short_description', { - target: 'title', - actionType: 'append', - }); - - await api.pushToService({ - externalService, - mapping, - params: apiParams, - secrets: {}, - logger: mockedLogger, - }); - expect(externalService.updateIncident).toHaveBeenCalledWith({ - incidentId: 'incident-3', - incident: { - severity: '1', - urgency: '2', - impact: '3', - short_description: - 'title from servicenow \r\nIncident title (updated at 2020-03-13T08:34:53.450Z by Elastic User)', + { + commentId: 'case-comment-2', + pushedDate: '2020-03-10T12:24:20.000Z', }, - }); - }); - - test('comment nothing', async () => { - mapping.set('title', { - target: 'short_description', - actionType: 'overwrite', - }); - - mapping.set('description', { - target: 'description', - actionType: 'nothing', - }); - - mapping.set('comments', { - target: 'comments', - actionType: 'nothing', - }); - - mapping.set('short_description', { - target: 'title', - actionType: 'overwrite', - }); - - await api.pushToService({ - externalService, - mapping, - params: apiParams, - secrets: {}, - logger: mockedLogger, - }); - expect(externalService.updateIncident).toHaveBeenCalledTimes(1); + ], + }); + }); + + test('it updates an incident without comments', async () => { + const params = { ...apiParams, comments: [] }; + const res = await api.pushToService({ + externalService, + mapping, + params, + secrets: {}, + logger: mockedLogger, + }); + + expect(res).toEqual({ + id: 'incident-2', + title: 'INC02', + pushedDate: '2020-03-10T12:24:20.000Z', + url: 'https://instance.service-now.com/nav_to.do?uri=incident.do?sys_id=123', + }); + }); + + test('it calls updateIncident correctly', async () => { + const params = { ...apiParams }; + await api.pushToService({ + externalService, + mapping, + params, + secrets: {}, + logger: mockedLogger, + }); + + expect(externalService.updateIncident).toHaveBeenCalledWith({ + incidentId: 'incident-3', + incident: { + severity: '1', + urgency: '2', + impact: '3', + description: 'Incident description (updated at 2020-03-13T08:34:53.450Z by Elastic User)', + short_description: 'Incident title (updated at 2020-03-13T08:34:53.450Z by Elastic User)', + }, + }); + expect(externalService.createIncident).not.toHaveBeenCalled(); + }); + + test('it calls updateIncident to create a comments correctly', async () => { + const params = { ...apiParams }; + await api.pushToService({ + externalService, + mapping, + params, + secrets: {}, + logger: mockedLogger, + }); + expect(externalService.updateIncident).toHaveBeenCalledTimes(3); + expect(externalService.updateIncident).toHaveBeenNthCalledWith(1, { + incident: { + severity: '1', + urgency: '2', + impact: '3', + description: 'Incident description (updated at 2020-03-13T08:34:53.450Z by Elastic User)', + short_description: 'Incident title (updated at 2020-03-13T08:34:53.450Z by Elastic User)', + }, + incidentId: 'incident-3', + }); + + expect(externalService.updateIncident).toHaveBeenNthCalledWith(2, { + incident: { + severity: '1', + urgency: '2', + impact: '3', + comments: 'A comment (added at 2020-03-13T08:34:53.450Z by Elastic User)', + description: 'Incident description (updated at 2020-03-13T08:34:53.450Z by Elastic User)', + short_description: 'Incident title (updated at 2020-03-13T08:34:53.450Z by Elastic User)', + }, + incidentId: 'incident-2', + }); + }); + }); + + describe('mapping variations', () => { + test('overwrite & append', async () => { + mapping.set('title', { + target: 'short_description', + actionType: 'overwrite', + }); + + mapping.set('description', { + target: 'description', + actionType: 'append', + }); + + mapping.set('comments', { + target: 'comments', + actionType: 'append', + }); + + mapping.set('short_description', { + target: 'title', + actionType: 'overwrite', + }); + + await api.pushToService({ + externalService, + mapping, + params: apiParams, + secrets: {}, + logger: mockedLogger, + }); + expect(externalService.updateIncident).toHaveBeenCalledWith({ + incidentId: 'incident-3', + incident: { + severity: '1', + urgency: '2', + impact: '3', + short_description: 'Incident title (updated at 2020-03-13T08:34:53.450Z by Elastic User)', + description: + 'description from servicenow \r\nIncident description (updated at 2020-03-13T08:34:53.450Z by Elastic User)', + }, + }); + }); + + test('nothing & append', async () => { + mapping.set('title', { + target: 'short_description', + actionType: 'nothing', + }); + + mapping.set('description', { + target: 'description', + actionType: 'append', + }); + + mapping.set('comments', { + target: 'comments', + actionType: 'append', + }); + + mapping.set('short_description', { + target: 'title', + actionType: 'nothing', + }); + + await api.pushToService({ + externalService, + mapping, + params: apiParams, + secrets: {}, + logger: mockedLogger, + }); + expect(externalService.updateIncident).toHaveBeenCalledWith({ + incidentId: 'incident-3', + incident: { + severity: '1', + urgency: '2', + impact: '3', + description: + 'description from servicenow \r\nIncident description (updated at 2020-03-13T08:34:53.450Z by Elastic User)', + }, + }); + }); + + test('append & append', async () => { + mapping.set('title', { + target: 'short_description', + actionType: 'append', + }); + + mapping.set('description', { + target: 'description', + actionType: 'append', + }); + + mapping.set('comments', { + target: 'comments', + actionType: 'append', + }); + + mapping.set('short_description', { + target: 'title', + actionType: 'append', + }); + + await api.pushToService({ + externalService, + mapping, + params: apiParams, + secrets: {}, + logger: mockedLogger, + }); + expect(externalService.updateIncident).toHaveBeenCalledWith({ + incidentId: 'incident-3', + incident: { + severity: '1', + urgency: '2', + impact: '3', + short_description: + 'title from servicenow \r\nIncident title (updated at 2020-03-13T08:34:53.450Z by Elastic User)', + description: + 'description from servicenow \r\nIncident description (updated at 2020-03-13T08:34:53.450Z by Elastic User)', + }, + }); + }); + + test('nothing & nothing', async () => { + mapping.set('title', { + target: 'short_description', + actionType: 'nothing', + }); + + mapping.set('description', { + target: 'description', + actionType: 'nothing', + }); + + mapping.set('comments', { + target: 'comments', + actionType: 'append', + }); + + mapping.set('short_description', { + target: 'title', + actionType: 'nothing', + }); + + await api.pushToService({ + externalService, + mapping, + params: apiParams, + secrets: {}, + logger: mockedLogger, + }); + + expect(externalService.updateIncident).toHaveBeenCalledWith({ + incidentId: 'incident-3', + incident: { + severity: '1', + urgency: '2', + impact: '3', + }, + }); + }); + + test('overwrite & nothing', async () => { + mapping.set('title', { + target: 'short_description', + actionType: 'overwrite', + }); + + mapping.set('description', { + target: 'description', + actionType: 'nothing', + }); + + mapping.set('comments', { + target: 'comments', + actionType: 'append', + }); + + mapping.set('short_description', { + target: 'title', + actionType: 'overwrite', + }); + + await api.pushToService({ + externalService, + mapping, + params: apiParams, + secrets: {}, + logger: mockedLogger, + }); + expect(externalService.updateIncident).toHaveBeenCalledWith({ + incidentId: 'incident-3', + incident: { + severity: '1', + urgency: '2', + impact: '3', + short_description: 'Incident title (updated at 2020-03-13T08:34:53.450Z by Elastic User)', + }, + }); + }); + + test('overwrite & overwrite', async () => { + mapping.set('title', { + target: 'short_description', + actionType: 'overwrite', + }); + + mapping.set('description', { + target: 'description', + actionType: 'overwrite', + }); + + mapping.set('comments', { + target: 'comments', + actionType: 'append', + }); + + mapping.set('short_description', { + target: 'title', + actionType: 'overwrite', + }); + + await api.pushToService({ + externalService, + mapping, + params: apiParams, + secrets: {}, + logger: mockedLogger, + }); + expect(externalService.updateIncident).toHaveBeenCalledWith({ + incidentId: 'incident-3', + incident: { + severity: '1', + urgency: '2', + impact: '3', + short_description: 'Incident title (updated at 2020-03-13T08:34:53.450Z by Elastic User)', + description: 'Incident description (updated at 2020-03-13T08:34:53.450Z by Elastic User)', + }, + }); + }); + + test('nothing & overwrite', async () => { + mapping.set('title', { + target: 'short_description', + actionType: 'nothing', + }); + + mapping.set('description', { + target: 'description', + actionType: 'overwrite', + }); + + mapping.set('comments', { + target: 'comments', + actionType: 'append', + }); + + mapping.set('short_description', { + target: 'title', + actionType: 'nothing', + }); + + await api.pushToService({ + externalService, + mapping, + params: apiParams, + secrets: {}, + logger: mockedLogger, + }); + expect(externalService.updateIncident).toHaveBeenCalledWith({ + incidentId: 'incident-3', + incident: { + severity: '1', + urgency: '2', + impact: '3', + description: 'Incident description (updated at 2020-03-13T08:34:53.450Z by Elastic User)', + }, + }); + }); + + test('append & overwrite', async () => { + mapping.set('title', { + target: 'short_description', + actionType: 'append', + }); + + mapping.set('description', { + target: 'description', + actionType: 'overwrite', + }); + + mapping.set('comments', { + target: 'comments', + actionType: 'append', + }); + + mapping.set('short_description', { + target: 'title', + actionType: 'append', + }); + + await api.pushToService({ + externalService, + mapping, + params: apiParams, + secrets: {}, + logger: mockedLogger, + }); + expect(externalService.updateIncident).toHaveBeenCalledWith({ + incidentId: 'incident-3', + incident: { + severity: '1', + urgency: '2', + impact: '3', + short_description: + 'title from servicenow \r\nIncident title (updated at 2020-03-13T08:34:53.450Z by Elastic User)', + description: 'Incident description (updated at 2020-03-13T08:34:53.450Z by Elastic User)', + }, + }); + }); + + test('append & nothing', async () => { + mapping.set('title', { + target: 'short_description', + actionType: 'append', + }); + + mapping.set('description', { + target: 'description', + actionType: 'nothing', + }); + + mapping.set('comments', { + target: 'comments', + actionType: 'append', + }); + + mapping.set('short_description', { + target: 'title', + actionType: 'append', + }); + + await api.pushToService({ + externalService, + mapping, + params: apiParams, + secrets: {}, + logger: mockedLogger, + }); + expect(externalService.updateIncident).toHaveBeenCalledWith({ + incidentId: 'incident-3', + incident: { + severity: '1', + urgency: '2', + impact: '3', + short_description: + 'title from servicenow \r\nIncident title (updated at 2020-03-13T08:34:53.450Z by Elastic User)', + }, + }); + }); + + test('comment nothing', async () => { + mapping.set('title', { + target: 'short_description', + actionType: 'overwrite', + }); + + mapping.set('description', { + target: 'description', + actionType: 'nothing', + }); + + mapping.set('comments', { + target: 'comments', + actionType: 'nothing', + }); + + mapping.set('short_description', { + target: 'title', + actionType: 'overwrite', + }); + + await api.pushToService({ + externalService, + mapping, + params: apiParams, + secrets: {}, + logger: mockedLogger, + }); + expect(externalService.updateIncident).toHaveBeenCalledTimes(1); + }); + }); + + describe('getFields', () => { + test('it returns the fields correctly', async () => { + const res = await api.getFields({ + externalService, + params: {}, }); + expect(res).toEqual(serviceNowCommonFields); }); }); }); diff --git a/x-pack/plugins/actions/server/builtin_action_types/servicenow/api.ts b/x-pack/plugins/actions/server/builtin_action_types/servicenow/api.ts index 6d12a3c92dac7..fbd8fdd635d70 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/servicenow/api.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/servicenow/api.ts @@ -12,6 +12,8 @@ import { PushToServiceApiParams, PushToServiceResponse, Incident, + GetCommonFieldsHandlerArgs, + GetCommonFieldsResponse, } from './types'; // TODO: to remove, need to support Case @@ -127,8 +129,16 @@ const pushToServiceHandler = async ({ return res; }; +const getFieldsHandler = async ({ + externalService, +}: GetCommonFieldsHandlerArgs): Promise => { + const res = await externalService.getFields(); + return res; +}; + export const api: ExternalServiceApi = { + getFields: getFieldsHandler, + getIncident: getIncidentHandler, handshake: handshakeHandler, pushToService: pushToServiceHandler, - getIncident: getIncidentHandler, }; diff --git a/x-pack/plugins/actions/server/builtin_action_types/servicenow/index.ts b/x-pack/plugins/actions/server/builtin_action_types/servicenow/index.ts index 41a577918b18e..d1182b0d3b2fa 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/servicenow/index.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/servicenow/index.ts @@ -25,6 +25,8 @@ import { ServiceNowPublicConfigurationType, ServiceNowSecretConfigurationType, PushToServiceResponse, + ExecutorSubActionCommonFieldsParams, + ServiceNowExecutorResultData, } from './types'; // TODO: to remove, need to support Case @@ -63,7 +65,7 @@ export function getActionType( } // action executor - +const supportedSubActions: string[] = ['getFields', 'pushToService']; async function executor( { logger }: { logger: Logger }, execOptions: ActionTypeExecutorOptions< @@ -71,10 +73,10 @@ async function executor( ServiceNowSecretConfigurationType, ExecutorParams > -): Promise> { +): Promise> { const { actionId, config, params, secrets } = execOptions; const { subAction, subActionParams } = params; - let data: PushToServiceResponse | null = null; + let data: ServiceNowExecutorResultData | null = null; const externalService = createExternalService( { @@ -91,7 +93,7 @@ async function executor( throw new Error(errorMessage); } - if (subAction !== 'pushToService') { + if (!supportedSubActions.includes(subAction)) { const errorMessage = `[Action][ExternalService] subAction ${subAction} not implemented.`; logger.error(errorMessage); throw new Error(errorMessage); @@ -117,5 +119,13 @@ async function executor( logger.debug(`response push to service for incident id: ${data.id}`); } + if (subAction === 'getFields') { + const getFieldsParams = subActionParams as ExecutorSubActionCommonFieldsParams; + data = await api.getFields({ + externalService, + params: getFieldsParams, + }); + } + return { status: 'ok', data: data ?? {}, actionId }; } diff --git a/x-pack/plugins/actions/server/builtin_action_types/servicenow/mocks.ts b/x-pack/plugins/actions/server/builtin_action_types/servicenow/mocks.ts index 7c2b1bd9d73c1..2351be36a50c4 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/servicenow/mocks.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/servicenow/mocks.ts @@ -7,8 +7,36 @@ import { ExternalService, PushToServiceApiParams, ExecutorSubActionPushParams } from './types'; import { MapRecord } from '../case/types'; +export const serviceNowCommonFields = [ + { + column_label: 'Close notes', + max_length: '4000', + element: 'close_notes', + }, + { + column_label: 'Description', + max_length: '4000', + element: 'description', + }, + { + column_label: 'Short description', + max_length: '160', + element: 'short_description', + }, + { + column_label: 'Created by', + max_length: '40', + element: 'sys_created_by', + }, + { + column_label: 'Updated by', + max_length: '40', + element: 'sys_updated_by', + }, +]; const createMock = (): jest.Mocked => { const service = { + getFields: jest.fn().mockImplementation(() => Promise.resolve(serviceNowCommonFields)), getIncident: jest.fn().mockImplementation(() => Promise.resolve({ short_description: 'title from servicenow', diff --git a/x-pack/plugins/actions/server/builtin_action_types/servicenow/schema.ts b/x-pack/plugins/actions/server/builtin_action_types/servicenow/schema.ts index 0dd70ea36636e..77c48aab1f309 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/servicenow/schema.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/servicenow/schema.ts @@ -28,6 +28,7 @@ export const ExternalIncidentServiceSecretConfigurationSchema = schema.object( ); export const ExecutorSubActionSchema = schema.oneOf([ + schema.literal('getFields'), schema.literal('getIncident'), schema.literal('pushToService'), schema.literal('handshake'), @@ -53,8 +54,13 @@ export const ExecutorSubActionGetIncidentParamsSchema = schema.object({ // Reserved for future implementation export const ExecutorSubActionHandshakeParamsSchema = schema.object({}); +export const ExecutorSubActionCommonFieldsParamsSchema = schema.object({}); export const ExecutorParamsSchema = schema.oneOf([ + schema.object({ + subAction: schema.literal('getFields'), + subActionParams: ExecutorSubActionCommonFieldsParamsSchema, + }), schema.object({ subAction: schema.literal('getIncident'), subActionParams: ExecutorSubActionGetIncidentParamsSchema, diff --git a/x-pack/plugins/actions/server/builtin_action_types/servicenow/service.test.ts b/x-pack/plugins/actions/server/builtin_action_types/servicenow/service.test.ts index 2adcdf561ce17..8ec80be1e2b09 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/servicenow/service.test.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/servicenow/service.test.ts @@ -11,6 +11,7 @@ import * as utils from '../lib/axios_utils'; import { ExternalService } from './types'; import { Logger } from '../../../../../../src/core/server'; import { loggingSystemMock } from '../../../../../../src/core/server/mocks'; +import { serviceNowCommonFields } from './mocks'; const logger = loggingSystemMock.create().get() as jest.Mocked; jest.mock('axios'); @@ -108,7 +109,7 @@ describe('ServiceNow service', () => { requestMock.mockImplementation(() => { throw new Error('An error has occurred'); }); - expect(service.getIncident('1')).rejects.toThrow( + await expect(service.getIncident('1')).rejects.toThrow( 'Unable to get incident with id 1. Error: An error has occurred' ); }); @@ -155,7 +156,7 @@ describe('ServiceNow service', () => { throw new Error('An error has occurred'); }); - expect( + await expect( service.createIncident({ incident: { short_description: 'title', description: 'desc' }, }) @@ -207,7 +208,7 @@ describe('ServiceNow service', () => { throw new Error('An error has occurred'); }); - expect( + await expect( service.updateIncident({ incidentId: '1', incident: { short_description: 'title', description: 'desc' }, @@ -234,4 +235,36 @@ describe('ServiceNow service', () => { }); }); }); + + describe('getFields', () => { + test('it should call request with correct arguments', async () => { + requestMock.mockImplementation(() => ({ + data: { result: serviceNowCommonFields }, + })); + await service.getFields(); + + expect(requestMock).toHaveBeenCalledWith({ + axios, + logger, + url: + 'https://dev102283.service-now.com/api/now/v2/table/sys_dictionary?sysparm_query=name=task^internal_type=string&active=true&read_only=false&sysparm_fields=max_length,element,column_label', + }); + }); + test('it returns common fields correctly', async () => { + requestMock.mockImplementation(() => ({ + data: { result: serviceNowCommonFields }, + })); + const res = await service.getFields(); + expect(res).toEqual(serviceNowCommonFields); + }); + + test('it should throw an error', async () => { + requestMock.mockImplementation(() => { + throw new Error('An error has occurred'); + }); + await expect(service.getFields()).rejects.toThrow( + 'Unable to get common fields. Error: An error has occurred' + ); + }); + }); }); diff --git a/x-pack/plugins/actions/server/builtin_action_types/servicenow/service.ts b/x-pack/plugins/actions/server/builtin_action_types/servicenow/service.ts index 9b1da4b4007c6..57f7176e2353c 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/servicenow/service.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/servicenow/service.ts @@ -16,6 +16,7 @@ import { ProxySettings } from '../../types'; const API_VERSION = 'v2'; const INCIDENT_URL = `api/now/${API_VERSION}/table/incident`; +const SYS_DICTIONARY = `api/now/${API_VERSION}/table/sys_dictionary`; // Based on: https://docs.servicenow.com/bundle/orlando-platform-user-interface/page/use/navigation/reference/r_NavigatingByURLExamples.html const VIEW_INCIDENT_URL = `nav_to.do?uri=incident.do?sys_id=`; @@ -33,6 +34,7 @@ export const createExternalService = ( } const incidentUrl = `${url}/${INCIDENT_URL}`; + const fieldsUrl = `${url}/${SYS_DICTIONARY}?sysparm_query=name=task^internal_type=string&active=true&read_only=false&sysparm_fields=max_length,element,column_label`; const axiosInstance = axios.create({ auth: { username, password }, }); @@ -126,10 +128,28 @@ export const createExternalService = ( } }; + const getFields = async () => { + try { + const res = await request({ + axios: axiosInstance, + url: fieldsUrl, + logger, + proxySettings, + }); + + return res.data.result.length > 0 ? res.data.result : []; + } catch (error) { + throw new Error( + getErrorMessage(i18n.NAME, `Unable to get common fields. Error: ${error.message}`) + ); + } + }; + return { - getIncident, createIncident, - updateIncident, findIncidents, + getFields, + getIncident, + updateIncident, }; }; diff --git a/x-pack/plugins/actions/server/builtin_action_types/servicenow/types.ts b/x-pack/plugins/actions/server/builtin_action_types/servicenow/types.ts index a6a0ac946fe96..0ee03f883ec05 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/servicenow/types.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/servicenow/types.ts @@ -8,12 +8,13 @@ import { TypeOf } from '@kbn/config-schema'; import { - ExternalIncidentServiceConfigurationSchema, - ExternalIncidentServiceSecretConfigurationSchema, ExecutorParamsSchema, - ExecutorSubActionPushParamsSchema, + ExecutorSubActionCommonFieldsParamsSchema, ExecutorSubActionGetIncidentParamsSchema, ExecutorSubActionHandshakeParamsSchema, + ExecutorSubActionPushParamsSchema, + ExternalIncidentServiceConfigurationSchema, + ExternalIncidentServiceSecretConfigurationSchema, } from './schema'; import { ActionsConfigurationUtilities } from '../../actions_config'; import { ExternalServiceCommentResponse } from '../case/types'; @@ -27,6 +28,12 @@ export type ServiceNowSecretConfigurationType = TypeOf< typeof ExternalIncidentServiceSecretConfigurationSchema >; +export type ExecutorSubActionCommonFieldsParams = TypeOf< + typeof ExecutorSubActionCommonFieldsParamsSchema +>; + +export type ServiceNowExecutorResultData = PushToServiceResponse | GetCommonFieldsResponse; + export interface CreateCommentRequest { [key: string]: string; } @@ -59,6 +66,7 @@ export interface PushToServiceResponse extends ExternalServiceIncidentResponse { export type ExternalServiceParams = Record; export interface ExternalService { + getFields: () => Promise; getIncident: (id: string) => Promise; createIncident: (params: ExternalServiceParams) => Promise; updateIncident: (params: ExternalServiceParams) => Promise; @@ -102,8 +110,24 @@ export interface GetIncidentApiHandlerArgs extends ExternalServiceApiHandlerArgs export interface HandshakeApiHandlerArgs extends ExternalServiceApiHandlerArgs { params: ExecutorSubActionHandshakeParams; } +export interface ExternalServiceFields { + column_label: string; + name: string; + internal_type: { + link: string; + value: string; + }; + max_length: string; + element: string; +} +export type GetCommonFieldsResponse = ExternalServiceFields[]; +export interface GetCommonFieldsHandlerArgs { + externalService: ExternalService; + params: ExecutorSubActionCommonFieldsParams; +} export interface ExternalServiceApi { + getFields: (args: GetCommonFieldsHandlerArgs) => Promise; handshake: (args: HandshakeApiHandlerArgs) => Promise; pushToService: (args: PushToServiceApiHandlerArgs) => Promise; getIncident: (args: GetIncidentApiHandlerArgs) => Promise; diff --git a/x-pack/plugins/apm/e2e/cypress/integration/apm.feature b/x-pack/plugins/apm/e2e/cypress/integration/apm.feature index 285615108266b..494a6b5fadb5b 100644 --- a/x-pack/plugins/apm/e2e/cypress/integration/apm.feature +++ b/x-pack/plugins/apm/e2e/cypress/integration/apm.feature @@ -3,5 +3,4 @@ Feature: APM Scenario: Transaction duration charts Given a user browses the APM UI application When the user inspects the opbeans-node service - Then should redirect to correct path with correct params - And should have correct y-axis ticks + Then should redirect to correct path with correct params \ No newline at end of file diff --git a/x-pack/plugins/apm/e2e/cypress/support/step_definitions/apm.ts b/x-pack/plugins/apm/e2e/cypress/support/step_definitions/apm.ts index 50c620dca9ddf..42c2bc7ffd318 100644 --- a/x-pack/plugins/apm/e2e/cypress/support/step_definitions/apm.ts +++ b/x-pack/plugins/apm/e2e/cypress/support/step_definitions/apm.ts @@ -29,16 +29,3 @@ Then(`should redirect to correct path with correct params`, () => { cy.url().should('contain', `/app/apm/services/opbeans-node/transactions`); cy.url().should('contain', `transactionType=request`); }); - -Then(`should have correct y-axis ticks`, () => { - const yAxisTick = - '[data-cy=transaction-duration-charts] .rv-xy-plot__axis--vertical .rv-xy-plot__axis__tick__text'; - - // wait for all loading to finish - cy.get('kbnLoadingIndicator').should('not.be.visible'); - - // literal assertions because snapshot() doesn't retry - cy.get(yAxisTick).eq(2).should('have.text', '55 ms'); - cy.get(yAxisTick).eq(1).should('have.text', '28 ms'); - cy.get(yAxisTick).eq(0).should('have.text', '0 ms'); -}); diff --git a/x-pack/plugins/apm/public/components/app/ErrorGroupDetails/Distribution/index.tsx b/x-pack/plugins/apm/public/components/app/ErrorGroupDetails/Distribution/index.tsx index e17dd9a9eb038..a17bf7e93e466 100644 --- a/x-pack/plugins/apm/public/components/app/ErrorGroupDetails/Distribution/index.tsx +++ b/x-pack/plugins/apm/public/components/app/ErrorGroupDetails/Distribution/index.tsx @@ -4,31 +4,24 @@ * you may not use this file except in compliance with the Elastic License. */ +import { + Axis, + Chart, + HistogramBarSeries, + niceTimeFormatter, + Position, + ScaleType, + Settings, + SettingsSpec, + TooltipValue, +} from '@elastic/charts'; import { EuiTitle } from '@elastic/eui'; -import theme from '@elastic/eui/dist/eui_theme_light.json'; -import numeral from '@elastic/numeral'; -import { i18n } from '@kbn/i18n'; import d3 from 'd3'; -import { scaleUtc } from 'd3-scale'; -import { mean } from 'lodash'; import React from 'react'; import { asRelativeDateTimeRange } from '../../../../../common/utils/formatters'; -import { getTimezoneOffsetInMs } from '../../../shared/charts/CustomPlot/getTimezoneOffsetInMs'; -// @ts-expect-error -import Histogram from '../../../shared/charts/Histogram'; -import { EmptyMessage } from '../../../shared/EmptyMessage'; - -interface IBucket { - key: number; - count: number | undefined; -} - -// TODO: cleanup duplication of this in distribution/get_distribution.ts (ErrorDistributionAPIResponse) and transactions/distribution/index.ts (TransactionDistributionAPIResponse) -interface IDistribution { - noHits: boolean; - buckets: IBucket[]; - bucketSize: number; -} +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import type { ErrorDistributionAPIResponse } from '../../../../../server/lib/errors/distribution/get_distribution'; +import { useTheme } from '../../../../hooks/useTheme'; interface FormattedBucket { x0: number; @@ -37,13 +30,9 @@ interface FormattedBucket { } export function getFormattedBuckets( - buckets: IBucket[], + buckets: ErrorDistributionAPIResponse['buckets'], bucketSize: number -): FormattedBucket[] | null { - if (!buckets) { - return null; - } - +): FormattedBucket[] { return buckets.map(({ count, key }) => { return { x0: key, @@ -54,76 +43,66 @@ export function getFormattedBuckets( } interface Props { - distribution: IDistribution; + distribution: ErrorDistributionAPIResponse; title: React.ReactNode; } -const tooltipHeader = (bucket: FormattedBucket) => - asRelativeDateTimeRange(bucket.x0, bucket.x); - export function ErrorDistribution({ distribution, title }: Props) { + const theme = useTheme(); const buckets = getFormattedBuckets( distribution.buckets, distribution.bucketSize ); - if (!buckets) { - return ( - - ); - } - - const averageValue = mean(buckets.map((bucket) => bucket.y)) || 0; const xMin = d3.min(buckets, (d) => d.x0); - const xMax = d3.max(buckets, (d) => d.x); - const tickFormat = scaleUtc().domain([xMin, xMax]).tickFormat(); + const xMax = d3.max(buckets, (d) => d.x0); + + const xFormatter = niceTimeFormatter([xMin, xMax]); + + const tooltipProps: SettingsSpec['tooltip'] = { + headerFormatter: (tooltip: TooltipValue) => { + const serie = buckets.find((bucket) => bucket.x0 === tooltip.value); + if (serie) { + return asRelativeDateTimeRange(serie.x0, serie.x); + } + return `${tooltip.value}`; + }, + }; return (
{title} - bucket.x} - xType="time-utc" - formatX={(value: Date) => { - const time = value.getTime(); - return tickFormat(new Date(time - getTimezoneOffsetInMs(time))); - }} - buckets={buckets} - bucketSize={distribution.bucketSize} - formatYShort={(value: number) => - i18n.translate('xpack.apm.errorGroupDetails.occurrencesShortLabel', { - defaultMessage: '{occCount} occ.', - values: { occCount: value }, - }) - } - formatYLong={(value: number) => - i18n.translate('xpack.apm.errorGroupDetails.occurrencesLongLabel', { - defaultMessage: - '{occCount} {occCount, plural, one {occurrence} other {occurrences}}', - values: { occCount: value }, - }) - } - legends={[ - { - color: theme.euiColorVis1, - // 0a abbreviates large whole numbers with metric prefixes like: 1000 = 1k, 32000 = 32k, 1000000 = 1m - legendValue: numeral(averageValue).format('0a'), - title: i18n.translate('xpack.apm.errorGroupDetails.avgLabel', { - defaultMessage: 'Avg.', - }), - legendClickDisabled: true, - }, - ]} - /> +
+ + + + + + +
); } diff --git a/x-pack/plugins/apm/public/components/app/TransactionDetails/Distribution/index.tsx b/x-pack/plugins/apm/public/components/app/TransactionDetails/Distribution/index.tsx index 67125d41635a9..bf1bda793179f 100644 --- a/x-pack/plugins/apm/public/components/app/TransactionDetails/Distribution/index.tsx +++ b/x-pack/plugins/apm/public/components/app/TransactionDetails/Distribution/index.tsx @@ -4,22 +4,37 @@ * you may not use this file except in compliance with the Elastic License. */ +import { + Axis, + Chart, + ElementClickListener, + GeometryValue, + HistogramBarSeries, + Position, + RectAnnotation, + ScaleType, + Settings, + SettingsSpec, + TooltipValue, + XYChartSeriesIdentifier, +} from '@elastic/charts'; import { EuiIconTip, EuiTitle } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import d3 from 'd3'; import { isEmpty } from 'lodash'; import React, { useCallback } from 'react'; import { ValuesType } from 'utility-types'; +import { useTheme } from '../../../../../../observability/public'; import { getDurationFormatter } from '../../../../../common/utils/formatters'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { TransactionDistributionAPIResponse } from '../../../../../server/lib/transactions/distribution'; +import type { TransactionDistributionAPIResponse } from '../../../../../server/lib/transactions/distribution'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { DistributionBucket } from '../../../../../server/lib/transactions/distribution/get_buckets'; +import type { DistributionBucket } from '../../../../../server/lib/transactions/distribution/get_buckets'; import { IUrlParams } from '../../../../context/UrlParamsContext/types'; -// @ts-expect-error -import Histogram from '../../../shared/charts/Histogram'; +import { FETCH_STATUS } from '../../../../hooks/useFetcher'; +import { unit } from '../../../../style/variables'; +import { ChartContainer } from '../../../shared/charts/chart_container'; import { EmptyMessage } from '../../../shared/EmptyMessage'; -import { LoadingStatePrompt } from '../../../shared/LoadingStatePrompt'; interface IChartPoint { x0: number; @@ -31,10 +46,10 @@ interface IChartPoint { } export function getFormattedBuckets( - buckets: DistributionBucket[], - bucketSize: number + buckets?: DistributionBucket[], + bucketSize?: number ) { - if (!buckets) { + if (!buckets || !bucketSize) { return []; } @@ -74,7 +89,7 @@ const getFormatYLong = (transactionType: string | undefined) => (t: number) => { 'xpack.apm.transactionDetails.transactionsDurationDistributionChart.requestTypeUnitLongLabel', { defaultMessage: - '{transCount, plural, =0 {# request} one {# request} other {# requests}}', + '{transCount, plural, =0 {request} one {request} other {requests}}', values: { transCount: t, }, @@ -84,7 +99,7 @@ const getFormatYLong = (transactionType: string | undefined) => (t: number) => { 'xpack.apm.transactionDetails.transactionsDurationDistributionChart.transactionTypeUnitLongLabel', { defaultMessage: - '{transCount, plural, =0 {# transaction} one {# transaction} other {# transactions}}', + '{transCount, plural, =0 {transaction} one {transaction} other {transactions}}', values: { transCount: t, }, @@ -95,21 +110,21 @@ const getFormatYLong = (transactionType: string | undefined) => (t: number) => { interface Props { distribution?: TransactionDistributionAPIResponse; urlParams: IUrlParams; - isLoading: boolean; + fetchStatus: FETCH_STATUS; bucketIndex: number; onBucketClick: ( bucket: ValuesType ) => void; } -export function TransactionDistribution(props: Props) { - const { - distribution, - urlParams: { transactionType }, - isLoading, - bucketIndex, - onBucketClick, - } = props; +export function TransactionDistribution({ + distribution, + urlParams: { transactionType }, + fetchStatus, + bucketIndex, + onBucketClick, +}: Props) { + const theme = useTheme(); /* eslint-disable-next-line react-hooks/exhaustive-deps */ const formatYShort = useCallback(getFormatYShort(transactionType), [ @@ -122,12 +137,10 @@ export function TransactionDistribution(props: Props) { ]); // no data in response - if (!distribution || distribution.noHits) { - // only show loading state if there is no data - else show stale data until new data has loaded - if (isLoading) { - return ; - } - + if ( + (!distribution || distribution.noHits) && + fetchStatus !== FETCH_STATUS.LOADING + ) { return ( { - return bucket.key === chartPoint.x0; - }); - - return clickedBucket; - } - const buckets = getFormattedBuckets( - distribution.buckets, - distribution.bucketSize + distribution?.buckets, + distribution?.bucketSize ); - const xMax = d3.max(buckets, (d) => d.x) || 0; + const xMin = d3.min(buckets, (d) => d.x0) || 0; + const xMax = d3.max(buckets, (d) => d.x0) || 0; const timeFormatter = getDurationFormatter(xMax); + const tooltipProps: SettingsSpec['tooltip'] = { + headerFormatter: (tooltip: TooltipValue) => { + const serie = buckets.find((bucket) => bucket.x0 === tooltip.value); + if (serie) { + const xFormatted = timeFormatter(serie.x); + const x0Formatted = timeFormatter(serie.x0); + return `${x0Formatted.value} - ${xFormatted.value} ${xFormatted.unit}`; + } + return `${timeFormatter(tooltip.value)}`; + }, + }; + + const onBarClick: ElementClickListener = (elements) => { + const chartPoint = elements[0][0] as GeometryValue; + const clickedBucket = distribution?.buckets.find((bucket) => { + return bucket.key === chartPoint.x; + }); + if (clickedBucket) { + onBucketClick(clickedBucket); + } + }; + + const selectedBucket = buckets[bucketIndex]; + return (
@@ -181,42 +211,66 @@ export function TransactionDistribution(props: Props) { /> - - { - const clickedBucket = getBucketFromChartPoint(chartPoint); - - if (clickedBucket) { - onBucketClick(clickedBucket); - } - }} - formatX={(time: number) => timeFormatter(time).formatted} - formatYShort={formatYShort} - formatYLong={formatYLong} - verticalLineHover={(point: IChartPoint) => - isEmpty(getBucketFromChartPoint(point)?.samples) - } - backgroundHover={(point: IChartPoint) => - !isEmpty(getBucketFromChartPoint(point)?.samples) - } - tooltipHeader={(point: IChartPoint) => { - const xFormatted = timeFormatter(point.x); - const x0Formatted = timeFormatter(point.x0); - return `${x0Formatted.value} - ${xFormatted.value} ${xFormatted.unit}`; - }} - tooltipFooter={(point: IChartPoint) => - isEmpty(getBucketFromChartPoint(point)?.samples) && - i18n.translate( - 'xpack.apm.transactionDetails.transactionsDurationDistributionChart.noSampleTooltip', - { - defaultMessage: 'No sample available for this bucket', - } - ) - } - /> + + + + {selectedBucket && ( + + )} + timeFormatter(time).formatted} + /> + formatYShort(value)} + /> + value} + minBarHeight={2} + id="transactionDurationDistribution" + name={(series: XYChartSeriesIdentifier) => { + const bucketCount = series.splitAccessors.get( + series.yAccessor + ) as number; + return formatYLong(bucketCount); + }} + splitSeriesAccessors={['y']} + xScaleType={ScaleType.Linear} + yScaleType={ScaleType.Linear} + xAccessor="x0" + yAccessors={['y']} + data={buckets} + color={theme.eui.euiColorVis1} + /> + +
); } diff --git a/x-pack/plugins/apm/public/components/app/TransactionDetails/index.tsx b/x-pack/plugins/apm/public/components/app/TransactionDetails/index.tsx index efdd7b1f34221..e4c36b028e55c 100644 --- a/x-pack/plugins/apm/public/components/app/TransactionDetails/index.tsx +++ b/x-pack/plugins/apm/public/components/app/TransactionDetails/index.tsx @@ -52,7 +52,11 @@ export function TransactionDetails({ status: distributionStatus, } = useTransactionDistribution(urlParams); - const { data: transactionChartsData } = useTransactionCharts(); + const { + data: transactionChartsData, + status: transactionChartsStatus, + } = useTransactionCharts(); + const { waterfall, exceedsMax, status: waterfallStatus } = useWaterfall( urlParams ); @@ -121,6 +125,7 @@ export function TransactionDetails({ @@ -131,7 +136,7 @@ export function TransactionDetails({ { diff --git a/x-pack/plugins/apm/public/components/app/TransactionOverview/TransactionOverview.test.tsx b/x-pack/plugins/apm/public/components/app/TransactionOverview/TransactionOverview.test.tsx index b7d1b93600a73..c530a7e1489ad 100644 --- a/x-pack/plugins/apm/public/components/app/TransactionOverview/TransactionOverview.test.tsx +++ b/x-pack/plugins/apm/public/components/app/TransactionOverview/TransactionOverview.test.tsx @@ -4,12 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - fireEvent, - getByText, - queryByLabelText, - render, -} from '@testing-library/react'; +import { fireEvent, getByText, queryByLabelText } from '@testing-library/react'; import { createMemoryHistory } from 'history'; import { CoreStart } from 'kibana/public'; import React from 'react'; @@ -20,7 +15,10 @@ import { UrlParamsProvider } from '../../../context/UrlParamsContext'; import { IUrlParams } from '../../../context/UrlParamsContext/types'; import * as useFetcherHook from '../../../hooks/useFetcher'; import * as useServiceTransactionTypesHook from '../../../hooks/useServiceTransactionTypes'; -import { disableConsoleWarning } from '../../../utils/testHelpers'; +import { + disableConsoleWarning, + renderWithTheme, +} from '../../../utils/testHelpers'; import { fromQuery } from '../../shared/Links/url_helpers'; import { TransactionOverview } from './'; @@ -54,7 +52,7 @@ function setup({ jest.spyOn(useFetcherHook, 'useFetcher').mockReturnValue({} as any); - return render( + return renderWithTheme( diff --git a/x-pack/plugins/apm/public/components/app/TransactionOverview/index.tsx b/x-pack/plugins/apm/public/components/app/TransactionOverview/index.tsx index 5444d2d521f37..df9e673ed4847 100644 --- a/x-pack/plugins/apm/public/components/app/TransactionOverview/index.tsx +++ b/x-pack/plugins/apm/public/components/app/TransactionOverview/index.tsx @@ -22,7 +22,7 @@ import React, { useMemo } from 'react'; import { useLocation } from 'react-router-dom'; import { useTrackPageview } from '../../../../../observability/public'; import { Projection } from '../../../../common/projections'; -import { LegacyChartsSyncContextProvider as ChartsSyncContextProvider } from '../../../context/charts_sync_context'; +import { TRANSACTION_PAGE_LOAD } from '../../../../common/transaction_types'; import { IUrlParams } from '../../../context/UrlParamsContext/types'; import { useServiceTransactionTypes } from '../../../hooks/useServiceTransactionTypes'; import { useTransactionCharts } from '../../../hooks/useTransactionCharts'; @@ -33,11 +33,10 @@ import { ElasticDocsLink } from '../../shared/Links/ElasticDocsLink'; import { fromQuery, toQuery } from '../../shared/Links/url_helpers'; import { LocalUIFilters } from '../../shared/LocalUIFilters'; import { TransactionTypeFilter } from '../../shared/LocalUIFilters/TransactionTypeFilter'; +import { Correlations } from '../Correlations'; import { TransactionList } from './TransactionList'; import { useRedirect } from './useRedirect'; -import { TRANSACTION_PAGE_LOAD } from '../../../../common/transaction_types'; import { UserExperienceCallout } from './user_experience_callout'; -import { Correlations } from '../Correlations'; function getRedirectLocation({ urlParams, @@ -83,7 +82,10 @@ export function TransactionOverview({ serviceName }: TransactionOverviewProps) { }) ); - const { data: transactionCharts } = useTransactionCharts(); + const { + data: transactionCharts, + status: transactionChartsStatus, + } = useTransactionCharts(); useTrackPageview({ app: 'apm', path: 'transaction_overview' }); useTrackPageview({ app: 'apm', path: 'transaction_overview', delay: 15000 }); @@ -135,12 +137,11 @@ export function TransactionOverview({ serviceName }: TransactionOverviewProps) { )} - - - + @@ -190,7 +191,7 @@ export function TransactionOverview({ serviceName }: TransactionOverviewProps) { diff --git a/x-pack/plugins/apm/public/components/app/service_overview/index.tsx b/x-pack/plugins/apm/public/components/app/service_overview/index.tsx index 342152b572f1e..016ee3daf6b51 100644 --- a/x-pack/plugins/apm/public/components/app/service_overview/index.tsx +++ b/x-pack/plugins/apm/public/components/app/service_overview/index.tsx @@ -11,7 +11,7 @@ import styled from 'styled-components'; import { useTrackPageview } from '../../../../../observability/public'; import { isRumAgentName } from '../../../../common/agent_name'; import { ChartsSyncContextProvider } from '../../../context/charts_sync_context'; -import { ErroneousTransactionsRateChart } from '../../shared/charts/erroneous_transactions_rate_chart'; +import { TransactionErrorRateChart } from '../../shared/charts/transaction_error_rate_chart'; import { ErrorOverviewLink } from '../../shared/Links/apm/ErrorOverviewLink'; import { ServiceMapLink } from '../../shared/Links/apm/ServiceMapLink'; import { TransactionOverviewLink } from '../../shared/Links/apm/TransactionOverviewLink'; @@ -125,19 +125,7 @@ export function ServiceOverview({ {!isRumAgentName(agentName) && ( - - -

- {i18n.translate( - 'xpack.apm.serviceOverview.errorRateChartTitle', - { - defaultMessage: 'Error rate', - } - )} -

-
- -
+
)} diff --git a/x-pack/plugins/apm/public/components/shared/TransactionBreakdown/TransactionBreakdownGraph/index.tsx b/x-pack/plugins/apm/public/components/shared/TransactionBreakdown/TransactionBreakdownGraph/index.tsx index b908eb8da4d03..05cae589c19fc 100644 --- a/x-pack/plugins/apm/public/components/shared/TransactionBreakdown/TransactionBreakdownGraph/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/TransactionBreakdown/TransactionBreakdownGraph/index.tsx @@ -4,62 +4,113 @@ * you may not use this file except in compliance with the Elastic License. */ -import { throttle } from 'lodash'; -import React, { useMemo } from 'react'; +import { + AreaSeries, + Axis, + Chart, + niceTimeFormatter, + Placement, + Position, + ScaleType, + Settings, +} from '@elastic/charts'; +import moment from 'moment'; +import React, { useEffect } from 'react'; +import { useHistory } from 'react-router-dom'; import { asPercent } from '../../../../../common/utils/formatters'; -import { useUiTracker } from '../../../../../../observability/public'; -import { NOT_AVAILABLE_LABEL } from '../../../../../common/i18n'; -import { Maybe } from '../../../../../typings/common'; -import { Coordinate, TimeSeries } from '../../../../../typings/timeseries'; +import { TimeSeries } from '../../../../../typings/timeseries'; +import { FETCH_STATUS } from '../../../../hooks/useFetcher'; import { useUrlParams } from '../../../../hooks/useUrlParams'; -import { isValidCoordinateValue } from '../../../../utils/isValidCoordinateValue'; -import { getEmptySeries } from '../../charts/CustomPlot/getEmptySeries'; -import { TransactionLineChart } from '../../charts/TransactionCharts/TransactionLineChart'; +import { useChartsSync as useChartsSync2 } from '../../../../hooks/use_charts_sync'; +import { unit } from '../../../../style/variables'; +import { Annotations } from '../../charts/annotations'; +import { ChartContainer } from '../../charts/chart_container'; +import { onBrushEnd } from '../../charts/helper/helper'; + +const XY_HEIGHT = unit * 16; interface Props { - timeseries: TimeSeries[]; - noHits: boolean; + fetchStatus: FETCH_STATUS; + timeseries?: TimeSeries[]; } -const tickFormatY = (y: Maybe) => { - return asPercent(y ?? 0, 1); -}; +export function TransactionBreakdownGraph({ fetchStatus, timeseries }: Props) { + const history = useHistory(); + const chartRef = React.createRef(); + const { event, setEvent } = useChartsSync2(); + const { urlParams } = useUrlParams(); + const { start, end } = urlParams; -const formatTooltipValue = (coordinate: Coordinate) => { - return isValidCoordinateValue(coordinate.y) - ? asPercent(coordinate.y, 1) - : NOT_AVAILABLE_LABEL; -}; + useEffect(() => { + if (event.chartId !== 'timeSpentBySpan' && chartRef.current) { + chartRef.current.dispatchExternalPointerEvent(event); + } + }, [chartRef, event]); -function TransactionBreakdownGraph({ timeseries, noHits }: Props) { - const { urlParams } = useUrlParams(); - const { rangeFrom, rangeTo } = urlParams; - const trackApmEvent = useUiTracker({ app: 'apm' }); - const handleHover = useMemo( - () => - throttle(() => trackApmEvent({ metric: 'hover_breakdown_chart' }), 60000), - [trackApmEvent] - ); + const min = moment.utc(start).valueOf(); + const max = moment.utc(end).valueOf(); - const emptySeries = - rangeFrom && rangeTo - ? getEmptySeries( - new Date(rangeFrom).getTime(), - new Date(rangeTo).getTime() - ) - : []; + const xFormatter = niceTimeFormatter([min, max]); return ( - + + + onBrushEnd({ x, history })} + showLegend + showLegendExtra + legendPosition={Position.Bottom} + xDomain={{ min, max }} + flatLegend + onPointerUpdate={(currEvent: any) => { + setEvent(currEvent); + }} + externalPointerEvents={{ + tooltip: { visible: true, placement: Placement.Bottom }, + }} + /> + + asPercent(y ?? 0, 1)} + /> + + + + {timeseries?.length ? ( + timeseries.map((serie) => { + return ( + + ); + }) + ) : ( + // When timeseries is empty, loads an AreaSeries chart to show the default empty message. + + )} + + ); } - -export { TransactionBreakdownGraph }; diff --git a/x-pack/plugins/apm/public/components/shared/TransactionBreakdown/index.tsx b/x-pack/plugins/apm/public/components/shared/TransactionBreakdown/index.tsx index 55826497ca385..9b0c041aaf7b5 100644 --- a/x-pack/plugins/apm/public/components/shared/TransactionBreakdown/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/TransactionBreakdown/index.tsx @@ -5,16 +5,13 @@ */ import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiTitle } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { isEmpty } from 'lodash'; import React from 'react'; -import { FETCH_STATUS } from '../../../hooks/useFetcher'; import { useTransactionBreakdown } from '../../../hooks/useTransactionBreakdown'; import { TransactionBreakdownGraph } from './TransactionBreakdownGraph'; function TransactionBreakdown() { const { data, status } = useTransactionBreakdown(); const { timeseries } = data; - const noHits = isEmpty(timeseries) && status === FETCH_STATUS.SUCCESS; return ( @@ -29,7 +26,10 @@ function TransactionBreakdown() { - +
diff --git a/x-pack/plugins/apm/public/components/shared/charts/Histogram/SingleRect.js b/x-pack/plugins/apm/public/components/shared/charts/Histogram/SingleRect.js deleted file mode 100644 index ca85ee961f5d8..0000000000000 --- a/x-pack/plugins/apm/public/components/shared/charts/Histogram/SingleRect.js +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import PropTypes from 'prop-types'; - -function SingleRect({ innerHeight, marginTop, style, x, width }) { - return ( - - ); -} - -SingleRect.requiresSVG = true; -SingleRect.propTypes = { - x: PropTypes.number.isRequired, -}; - -export default SingleRect; diff --git a/x-pack/plugins/apm/public/components/shared/charts/Histogram/__test__/Histogram.test.js b/x-pack/plugins/apm/public/components/shared/charts/Histogram/__test__/Histogram.test.js deleted file mode 100644 index 03fd039a3401e..0000000000000 --- a/x-pack/plugins/apm/public/components/shared/charts/Histogram/__test__/Histogram.test.js +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; - -import d3 from 'd3'; -import { HistogramInner } from '../index'; -import response from './response.json'; -import { - disableConsoleWarning, - toJson, - mountWithTheme, -} from '../../../../../utils/testHelpers'; -import { getFormattedBuckets } from '../../../../app/TransactionDetails/Distribution/index'; -import { - asInteger, - getDurationFormatter, -} from '../../../../../../common/utils/formatters'; - -describe('Histogram', () => { - let mockConsole; - let wrapper; - - const onClick = jest.fn(); - - beforeAll(() => { - mockConsole = disableConsoleWarning('Warning: componentWillReceiveProps'); - }); - - afterAll(() => { - mockConsole.mockRestore(); - }); - - beforeEach(() => { - const buckets = getFormattedBuckets(response.buckets, response.bucketSize); - const xMax = d3.max(buckets, (d) => d.x); - const timeFormatter = getDurationFormatter(xMax); - - wrapper = mountWithTheme( - timeFormatter(time).formatted} - formatYShort={(t) => `${asInteger(t)} occ.`} - formatYLong={(t) => `${asInteger(t)} occurrences`} - tooltipHeader={(bucket) => { - const xFormatted = timeFormatter(bucket.x); - const x0Formatted = timeFormatter(bucket.x0); - return `${x0Formatted.value} - ${xFormatted.value} ${xFormatted.unit}`; - }} - width={800} - /> - ); - }); - - describe('Initially', () => { - it('should have default markup', () => { - expect(toJson(wrapper)).toMatchSnapshot(); - }); - - it('should not show tooltip', () => { - expect(wrapper.find('Tooltip').length).toBe(0); - }); - }); - - describe('when hovering over an empty bucket', () => { - beforeEach(() => { - wrapper.find('.rv-voronoi__cell').at(2).simulate('mouseOver'); - }); - - it('should not display tooltip', () => { - expect(wrapper.find('Tooltip').length).toBe(0); - }); - }); - - describe('when hovering over a non-empty bucket', () => { - beforeEach(() => { - wrapper.find('.rv-voronoi__cell').at(7).simulate('mouseOver'); - }); - - it('should display tooltip', () => { - const tooltips = wrapper.find('Tooltip'); - - expect(tooltips.length).toBe(1); - expect(tooltips.prop('header')).toBe('811 - 927 ms'); - expect(tooltips.prop('tooltipPoints')).toEqual([ - { value: '49 occurrences' }, - ]); - expect(tooltips.prop('x')).toEqual(869010); - expect(tooltips.prop('y')).toEqual(27.5); - }); - - it('should have correct markup for tooltip', () => { - const tooltips = wrapper.find('Tooltip'); - expect(toJson(tooltips)).toMatchSnapshot(); - }); - }); - - describe('when clicking on a non-empty bucket', () => { - beforeEach(() => { - wrapper.find('.rv-voronoi__cell').at(7).simulate('click'); - }); - - it('should call onClick with bucket', () => { - expect(onClick).toHaveBeenCalledWith({ - style: { cursor: 'pointer' }, - xCenter: 869010, - x0: 811076, - x: 926944, - y: 49, - }); - }); - }); -}); diff --git a/x-pack/plugins/apm/public/components/shared/charts/Histogram/__test__/__snapshots__/Histogram.test.js.snap b/x-pack/plugins/apm/public/components/shared/charts/Histogram/__test__/__snapshots__/Histogram.test.js.snap deleted file mode 100644 index a31b9735628ab..0000000000000 --- a/x-pack/plugins/apm/public/components/shared/charts/Histogram/__test__/__snapshots__/Histogram.test.js.snap +++ /dev/null @@ -1,1504 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Histogram Initially should have default markup 1`] = ` -.c0 { - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - position: absolute; - top: 0; - left: 0; -} - -
- -
-
- - - - - - - - - - - - - 0 ms - - - - - - 500 ms - - - - - - 1,000 ms - - - - - - 1,500 ms - - - - - - 2,000 ms - - - - - - 2,500 ms - - - - - - 3,000 ms - - - - - - - - - - 0 occ. - - - - - - 28 occ. - - - - - - 55 occ. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
-
-`; - -exports[`Histogram when hovering over a non-empty bucket should have correct markup for tooltip 1`] = ` -.c0 { - margin: 0 16px; - -webkit-transform: translateY(-50%); - -ms-transform: translateY(-50%); - transform: translateY(-50%); - border: 1px solid #d3dae6; - background: #ffffff; - border-radius: 4px; - font-size: 14px; - color: #000000; -} - -.c1 { - background: #f5f7fa; - border-bottom: 1px solid #d3dae6; - border-radius: 4px 4px 0 0; - padding: 8px; - color: #98a2b3; -} - -.c2 { - margin: 8px; - margin-right: 16px; - font-size: 12px; -} - -.c4 { - color: #98a2b3; - margin: 8px; - font-size: 12px; -} - -.c3 { - color: #69707d; - font-size: 14px; -} - -
- -
- -
- 811 - 927 ms -
-
- -
- -
- 49 occurrences -
-
-
-
- -
- -
-
-
-`; diff --git a/x-pack/plugins/apm/public/components/shared/charts/Histogram/__test__/response.json b/x-pack/plugins/apm/public/components/shared/charts/Histogram/__test__/response.json deleted file mode 100644 index 302e105dfa997..0000000000000 --- a/x-pack/plugins/apm/public/components/shared/charts/Histogram/__test__/response.json +++ /dev/null @@ -1,106 +0,0 @@ -{ - "buckets": [ - { "key": 0, "count": 0 }, - { "key": 115868, "count": 0 }, - { "key": 231736, "count": 0 }, - { "key": 347604, "count": 0 }, - { "key": 463472, "count": 0 }, - { - "key": 579340, - "count": 8, - "samples": [ - { - "transactionId": "99437ee4-08d4-41f5-9b2b-93cc32ec3dfb" - } - ] - }, - { - "key": 695208, - "count": 23, - "samples": [ - { - "transactionId": "d327611b-e999-4942-a94f-c60208940180" - } - ] - }, - { - "key": 811076, - "count": 49, - "samples": [ - { - "transactionId": "99c50a5b-44b4-4289-a3d1-a2815d128192" - } - ] - }, - { - "key": 926944, - "count": 51, - "transactionId": "9706a1ec-23f5-4ce8-97e8-69ce35fb0a9a" - }, - { - "key": 1042812, - "count": 46, - "transactionId": "f8d360c3-dd5e-47b6-b082-9e0bf821d3b2" - }, - { - "key": 1158680, - "count": 13, - "samples": [ - { - "transactionId": "8486d3e2-7f15-48df-aa37-6ee9955adbd2" - } - ] - }, - { - "key": 1274548, - "count": 7, - "transactionId": "54b4b5a7-f065-4cab-9016-534e58f4fc0a" - }, - { - "key": 1390416, - "count": 4, - "transactionId": "8cfac2a3-38e7-4d3a-9792-d008b4bcb867" - }, - { - "key": 1506284, - "count": 3, - "transactionId": "ce3f3bd3-a37c-419e-bb9c-5db956ded149" - }, - { "key": 1622152, "count": 0 }, - { - "key": 1738020, - "count": 4, - "transactionId": "2300174b-85d8-40ba-a6cb-eeba2a49debf" - }, - { "key": 1853888, "count": 0 }, - { "key": 1969756, "count": 0 }, - { - "key": 2085624, - "count": 1, - "transactionId": "774955a4-2ba3-4461-81a6-65759db4805d" - }, - { "key": 2201492, "count": 0 }, - { "key": 2317360, "count": 0 }, - { "key": 2433228, "count": 0 }, - { "key": 2549096, "count": 0 }, - { "key": 2664964, "count": 0 }, - { - "key": 2780832, - "count": 1, - "transactionId": "035d1b9d-af71-46cf-8910-57bd4faf412d" - }, - { - "key": 2896700, - "count": 1, - "transactionId": "4a845b32-9de4-4796-8ef4-d7bbdedc9099" - }, - { "key": 3012568, "count": 0 }, - { - "key": 3128436, - "count": 1, - "transactionId": "68620ffb-7a1b-4f8e-b9bb-009fa5b092be" - } - ], - "bucketSize": 115868, - "defaultBucketIndex": 12 -} diff --git a/x-pack/plugins/apm/public/components/shared/charts/Histogram/index.js b/x-pack/plugins/apm/public/components/shared/charts/Histogram/index.js deleted file mode 100644 index 3b2109d68c613..0000000000000 --- a/x-pack/plugins/apm/public/components/shared/charts/Histogram/index.js +++ /dev/null @@ -1,319 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React, { PureComponent } from 'react'; -import d3 from 'd3'; -import { isEmpty } from 'lodash'; -import PropTypes from 'prop-types'; -import { scaleLinear } from 'd3-scale'; -import styled from 'styled-components'; -import SingleRect from './SingleRect'; -import { - XYPlot, - XAxis, - YAxis, - HorizontalGridLines, - VerticalRectSeries, - Voronoi, - makeWidthFlexible, - VerticalGridLines, -} from 'react-vis'; -import { unit } from '../../../../style/variables'; -import Tooltip from '../Tooltip'; -import theme from '@elastic/eui/dist/eui_theme_light.json'; -import { tint } from 'polished'; -import { getTimeTicksTZ, getDomainTZ } from '../helper/timezone'; -import Legends from '../CustomPlot/Legends'; -import StatusText from '../CustomPlot/StatusText'; -import { i18n } from '@kbn/i18n'; -import { isValidCoordinateValue } from '../../../../utils/isValidCoordinateValue'; - -const XY_HEIGHT = unit * 10; -const XY_MARGIN = { - top: unit, - left: unit * 5, - right: unit, - bottom: unit * 2, -}; - -const X_TICK_TOTAL = 8; - -// position absolutely to make sure that window resizing/zooming works -const ChartsWrapper = styled.div` - user-select: none; - position: absolute; - top: 0; - left: 0; -`; - -export class HistogramInner extends PureComponent { - constructor(props) { - super(props); - this.state = { - hoveredBucket: {}, - }; - } - - onClick = (bucket) => { - if (this.props.onClick) { - this.props.onClick(bucket); - } - }; - - onHover = (bucket) => { - this.setState({ hoveredBucket: bucket }); - }; - - onBlur = () => { - this.setState({ hoveredBucket: {} }); - }; - - getChartData(items, selectedItem) { - const yMax = d3.max(items, (d) => d.y); - const MINIMUM_BUCKET_SIZE = yMax * 0.02; - - return items.map((item) => { - const padding = (item.x - item.x0) / 20; - return { - ...item, - color: - item === selectedItem - ? theme.euiColorVis1 - : tint(0.5, theme.euiColorVis1), - x0: item.x0 + padding, - x: item.x - padding, - y: item.y > 0 ? Math.max(item.y, MINIMUM_BUCKET_SIZE) : 0, - }; - }); - } - - render() { - const { - backgroundHover, - bucketIndex, - buckets, - bucketSize, - formatX, - formatYShort, - formatYLong, - tooltipFooter, - tooltipHeader, - verticalLineHover, - width: XY_WIDTH, - height, - legends, - } = this.props; - const { hoveredBucket } = this.state; - if (isEmpty(buckets) || XY_WIDTH === 0) { - return null; - } - - const isTimeSeries = - this.props.xType === 'time' || this.props.xType === 'time-utc'; - - const xMin = d3.min(buckets, (d) => d.x0); - const xMax = d3.max(buckets, (d) => d.x); - const yMin = 0; - const yMax = d3.max(buckets, (d) => d.y); - const selectedBucket = buckets[bucketIndex]; - const chartData = this.getChartData(buckets, selectedBucket); - - const x = scaleLinear() - .domain([xMin, xMax]) - .range([XY_MARGIN.left, XY_WIDTH - XY_MARGIN.right]); - - const y = scaleLinear().domain([yMin, yMax]).range([XY_HEIGHT, 0]).nice(); - - const [xMinZone, xMaxZone] = getDomainTZ(xMin, xMax); - const xTickValues = isTimeSeries - ? getTimeTicksTZ({ - domain: [xMinZone, xMaxZone], - totalTicks: X_TICK_TOTAL, - width: XY_WIDTH, - }) - : undefined; - - const xDomain = x.domain(); - const yDomain = y.domain(); - const yTickValues = [0, yDomain[1] / 2, yDomain[1]]; - const shouldShowTooltip = - hoveredBucket.x > 0 && (hoveredBucket.y > 0 || isTimeSeries); - - const showVerticalLineHover = verticalLineHover(hoveredBucket); - const showBackgroundHover = backgroundHover(hoveredBucket); - - const hasValidCoordinates = buckets.some((bucket) => - isValidCoordinateValue(bucket.y) - ); - const noHits = this.props.noHits || !hasValidCoordinates; - - const xyPlotProps = { - dontCheckIfEmpty: true, - xType: this.props.xType, - width: XY_WIDTH, - height: XY_HEIGHT, - margin: XY_MARGIN, - xDomain: xDomain, - yDomain: yDomain, - }; - - const xAxisProps = { - style: { strokeWidth: '1px' }, - marginRight: 10, - tickSize: 0, - tickTotal: X_TICK_TOTAL, - tickFormat: formatX, - tickValues: xTickValues, - }; - - const emptyStateChart = ( - - - - - ); - - return ( -
- - {noHits ? ( - <>{emptyStateChart} - ) : ( - <> - - - - - - {showBackgroundHover && ( - - )} - - {shouldShowTooltip && ( - - )} - - {selectedBucket && ( - - )} - - - - {showVerticalLineHover && hoveredBucket?.x && ( - - )} - - { - return { - ...bucket, - xCenter: (bucket.x0 + bucket.x) / 2, - }; - })} - onClick={this.onClick} - onHover={this.onHover} - onBlur={this.onBlur} - x={(d) => x(d.xCenter)} - y={() => 1} - /> - - - {legends && ( - {}} - truncateLegends={false} - noHits={noHits} - /> - )} - - )} - -
- ); - } -} - -HistogramInner.propTypes = { - backgroundHover: PropTypes.func, - bucketIndex: PropTypes.number, - buckets: PropTypes.array.isRequired, - bucketSize: PropTypes.number.isRequired, - formatX: PropTypes.func, - formatYLong: PropTypes.func, - formatYShort: PropTypes.func, - onClick: PropTypes.func, - tooltipFooter: PropTypes.func, - tooltipHeader: PropTypes.func, - verticalLineHover: PropTypes.func, - width: PropTypes.number.isRequired, - height: PropTypes.number, - xType: PropTypes.string, - legends: PropTypes.array, - noHits: PropTypes.bool, -}; - -HistogramInner.defaultProps = { - backgroundHover: () => null, - formatYLong: (value) => value, - formatYShort: (value) => value, - tooltipFooter: () => null, - tooltipHeader: () => null, - verticalLineHover: () => null, - xType: 'linear', - noHits: false, - height: XY_HEIGHT, -}; - -export default makeWidthFlexible(HistogramInner); diff --git a/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/TransactionLineChart/index.tsx b/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/TransactionLineChart/index.tsx deleted file mode 100644 index 2e4b51af00d6b..0000000000000 --- a/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/TransactionLineChart/index.tsx +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React, { useCallback } from 'react'; -import { Coordinate, TimeSeries } from '../../../../../../typings/timeseries'; -import { useLegacyChartsSync as useChartsSync } from '../../../../../hooks/use_charts_sync'; -// @ts-expect-error -import CustomPlot from '../../CustomPlot'; - -interface Props { - series: TimeSeries[]; - truncateLegends?: boolean; - tickFormatY: (y: number) => React.ReactNode; - formatTooltipValue: (c: Coordinate) => React.ReactNode; - yMax?: string | number; - height?: number; - stacked?: boolean; - onHover?: () => void; - visibleLegendCount?: number; - onToggleLegend?: (disabledSeriesState: boolean[]) => void; -} - -function TransactionLineChart(props: Props) { - const { - series, - tickFormatY, - formatTooltipValue, - yMax = 'max', - height, - truncateLegends, - stacked = false, - onHover, - visibleLegendCount, - onToggleLegend, - } = props; - - const syncedChartsProps = useChartsSync(); - - // combine callback for syncedChartsProps.onHover and props.onHover - const combinedOnHover = useCallback( - (hoverX: number) => { - if (onHover) { - onHover(); - } - return syncedChartsProps.onHover(hoverX); - }, - [syncedChartsProps, onHover] - ); - - return ( - - ); -} - -export { TransactionLineChart }; diff --git a/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/index.tsx b/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/index.tsx index b3c0c3b6de857..2a5948d0ebf0b 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/index.tsx @@ -20,104 +20,107 @@ import { TRANSACTION_REQUEST, TRANSACTION_ROUTE_CHANGE, } from '../../../../../common/transaction_types'; +import { asDecimal, tpmUnit } from '../../../../../common/utils/formatters'; import { Coordinate } from '../../../../../typings/timeseries'; +import { ChartsSyncContextProvider } from '../../../../context/charts_sync_context'; import { LicenseContext } from '../../../../context/LicenseContext'; import { IUrlParams } from '../../../../context/UrlParamsContext/types'; +import { FETCH_STATUS } from '../../../../hooks/useFetcher'; import { ITransactionChartData } from '../../../../selectors/chartSelectors'; -import { asDecimal, tpmUnit } from '../../../../../common/utils/formatters'; import { isValidCoordinateValue } from '../../../../utils/isValidCoordinateValue'; -import { ErroneousTransactionsRateChart } from '../erroneous_transactions_rate_chart/legacy'; import { TransactionBreakdown } from '../../TransactionBreakdown'; -import { - getResponseTimeTickFormatter, - getResponseTimeTooltipFormatter, -} from './helper'; +import { LineChart } from '../line_chart'; +import { TransactionErrorRateChart } from '../transaction_error_rate_chart/'; +import { getResponseTimeTickFormatter } from './helper'; import { MLHeader } from './ml_header'; -import { TransactionLineChart } from './TransactionLineChart'; import { useFormatter } from './use_formatter'; interface TransactionChartProps { charts: ITransactionChartData; urlParams: IUrlParams; + fetchStatus: FETCH_STATUS; } export function TransactionCharts({ charts, urlParams, + fetchStatus, }: TransactionChartProps) { const getTPMFormatter = (t: number) => { - const unit = tpmUnit(urlParams.transactionType); - return `${asDecimal(t)} ${unit}`; + return `${asDecimal(t)} ${tpmUnit(urlParams.transactionType)}`; }; - const getTPMTooltipFormatter = (p: Coordinate) => { - return isValidCoordinateValue(p.y) - ? getTPMFormatter(p.y) - : NOT_AVAILABLE_LABEL; + const getTPMTooltipFormatter = (y: Coordinate['y']) => { + return isValidCoordinateValue(y) ? getTPMFormatter(y) : NOT_AVAILABLE_LABEL; }; const { transactionType } = urlParams; const { responseTimeSeries, tpmSeries } = charts; - const { formatter, setDisabledSeriesState } = useFormatter( - responseTimeSeries - ); + const { formatter, toggleSerie } = useFormatter(responseTimeSeries); return ( <> - - - - - - - {responseTimeLabel(transactionType)} - - - - {(license) => ( - - )} - - - - - + + + + + + + + {responseTimeLabel(transactionType)} + + + + {(license) => ( + + )} + + + { + if (serie) { + toggleSerie(serie); + } + }} + /> + + - - - - {tpmLabel(transactionType)} - - - - - + + + + {tpmLabel(transactionType)} + + + + + - + - - - - - - - - + + + + + + + + + ); } diff --git a/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/use_formatter.test.tsx b/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/use_formatter.test.tsx index fc873cbda7bf2..958a5db6b66c9 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/use_formatter.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/use_formatter.test.tsx @@ -3,38 +3,17 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; +import { SeriesIdentifier } from '@elastic/charts'; +import { renderHook } from '@testing-library/react-hooks'; +import { act } from 'react-test-renderer'; +import { toMicroseconds } from '../../../../../common/utils/formatters'; import { TimeSeries } from '../../../../../typings/timeseries'; import { useFormatter } from './use_formatter'; -import { render, fireEvent, act } from '@testing-library/react'; -import { toMicroseconds } from '../../../../../common/utils/formatters'; - -function MockComponent({ - timeSeries, - disabledSeries, - value, -}: { - timeSeries: TimeSeries[]; - disabledSeries: boolean[]; - value: number; -}) { - const { formatter, setDisabledSeriesState } = useFormatter(timeSeries); - - const onDisableSeries = () => { - setDisabledSeriesState(disabledSeries); - }; - - return ( -
- - {formatter(value).formatted} -
- ); -} describe('useFormatter', () => { const timeSeries = ([ { + title: 'avg', data: [ { x: 1, y: toMicroseconds(11, 'minutes') }, { x: 2, y: toMicroseconds(1, 'minutes') }, @@ -42,6 +21,7 @@ describe('useFormatter', () => { ], }, { + title: '95th percentile', data: [ { x: 1, y: toMicroseconds(120, 'seconds') }, { x: 2, y: toMicroseconds(1, 'minutes') }, @@ -49,6 +29,7 @@ describe('useFormatter', () => { ], }, { + title: '99th percentile', data: [ { x: 1, y: toMicroseconds(60, 'seconds') }, { x: 2, y: toMicroseconds(5, 'minutes') }, @@ -56,54 +37,47 @@ describe('useFormatter', () => { ], }, ] as unknown) as TimeSeries[]; + it('returns new formatter when disabled series state changes', () => { - const { getByText } = render( - - ); - expect(getByText('2.0 min')).toBeInTheDocument(); + const { result } = renderHook(() => useFormatter(timeSeries)); + expect( + result.current.formatter(toMicroseconds(120, 'seconds')).formatted + ).toEqual('2.0 min'); + act(() => { - fireEvent.click(getByText('disable series')); + result.current.toggleSerie({ + specId: 'avg', + } as SeriesIdentifier); }); - expect(getByText('120 s')).toBeInTheDocument(); + + expect( + result.current.formatter(toMicroseconds(120, 'seconds')).formatted + ).toEqual('120 s'); }); + it('falls back to the first formatter when disabled series is empty', () => { - const { getByText } = render( - - ); - expect(getByText('2.0 min')).toBeInTheDocument(); + const { result } = renderHook(() => useFormatter(timeSeries)); + expect( + result.current.formatter(toMicroseconds(120, 'seconds')).formatted + ).toEqual('2.0 min'); + act(() => { - fireEvent.click(getByText('disable series')); + result.current.toggleSerie({ + specId: 'avg', + } as SeriesIdentifier); }); - expect(getByText('2.0 min')).toBeInTheDocument(); - // const { formatter, setDisabledSeriesState } = useFormatter(timeSeries); - // expect(formatter(toMicroseconds(120, 'seconds'))).toEqual('2.0 min'); - // setDisabledSeriesState([true, true, false]); - // expect(formatter(toMicroseconds(120, 'seconds'))).toEqual('2.0 min'); - }); - it('falls back to the first formatter when disabled series is all true', () => { - const { getByText } = render( - - ); - expect(getByText('2.0 min')).toBeInTheDocument(); + + expect( + result.current.formatter(toMicroseconds(120, 'seconds')).formatted + ).toEqual('120 s'); + act(() => { - fireEvent.click(getByText('disable series')); + result.current.toggleSerie({ + specId: 'avg', + } as SeriesIdentifier); }); - expect(getByText('2.0 min')).toBeInTheDocument(); - // const { formatter, setDisabledSeriesState } = useFormatter(timeSeries); - // expect(formatter(toMicroseconds(120, 'seconds'))).toEqual('2.0 min'); - // setDisabledSeriesState([true, true, false]); - // expect(formatter(toMicroseconds(120, 'seconds'))).toEqual('2.0 min'); + expect( + result.current.formatter(toMicroseconds(120, 'seconds')).formatted + ).toEqual('2.0 min'); }); }); diff --git a/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/use_formatter.ts b/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/use_formatter.ts index d4694bc3caf1d..1475ec2934e95 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/use_formatter.ts +++ b/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/use_formatter.ts @@ -4,8 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { useState, Dispatch, SetStateAction } from 'react'; -import { isEmpty } from 'lodash'; +import { SeriesIdentifier } from '@elastic/charts'; +import { omit } from 'lodash'; +import { useState } from 'react'; import { getDurationFormatter, TimeFormatter, @@ -14,17 +15,36 @@ import { TimeSeries } from '../../../../../typings/timeseries'; import { getMaxY } from './helper'; export const useFormatter = ( - series: TimeSeries[] + series?: TimeSeries[] ): { formatter: TimeFormatter; - setDisabledSeriesState: Dispatch>; + toggleSerie: (disabledSerie: SeriesIdentifier) => void; } => { - const [disabledSeriesState, setDisabledSeriesState] = useState([]); - const visibleSeries = series.filter( - (serie, index) => disabledSeriesState[index] !== true + const [disabledSeries, setDisabledSeries] = useState< + Record + >({}); + + const visibleSeries = series?.filter( + (serie) => disabledSeries[serie.title] === undefined ); - const maxY = getMaxY(isEmpty(visibleSeries) ? series : visibleSeries); + + const maxY = getMaxY(visibleSeries || series || []); const formatter = getDurationFormatter(maxY); - return { formatter, setDisabledSeriesState }; + const toggleSerie = ({ specId }: SeriesIdentifier) => { + if (disabledSeries[specId] !== undefined) { + setDisabledSeries((prevState) => { + return omit(prevState, specId); + }); + } else { + setDisabledSeries((prevState) => { + return { ...prevState, [specId]: 0 }; + }); + } + }; + + return { + formatter, + toggleSerie, + }; }; diff --git a/x-pack/plugins/apm/public/components/shared/charts/annotations/index.tsx b/x-pack/plugins/apm/public/components/shared/charts/annotations/index.tsx new file mode 100644 index 0000000000000..683c66b2a96fe --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/charts/annotations/index.tsx @@ -0,0 +1,45 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { + AnnotationDomainTypes, + LineAnnotation, + Position, +} from '@elastic/charts'; +import { EuiIcon } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import React from 'react'; +import { asAbsoluteDateTime } from '../../../../../common/utils/formatters'; +import { useTheme } from '../../../../hooks/useTheme'; +import { useAnnotations } from '../../../../hooks/use_annotations'; + +export function Annotations() { + const { annotations } = useAnnotations(); + const theme = useTheme(); + + if (!annotations.length) { + return null; + } + + const color = theme.eui.euiColorSecondary; + + return ( + ({ + dataValue: annotation['@timestamp'], + header: asAbsoluteDateTime(annotation['@timestamp']), + details: `${i18n.translate('xpack.apm.chart.annotation.version', { + defaultMessage: 'Version', + })} ${annotation.text}`, + }))} + style={{ line: { strokeWidth: 1, stroke: color, opacity: 1 } }} + marker={} + markerPosition={Position.Top} + /> + ); +} diff --git a/x-pack/plugins/apm/public/components/shared/charts/chart_container.test.tsx b/x-pack/plugins/apm/public/components/shared/charts/chart_container.test.tsx index 409cb69575ca9..c0e8f869ce647 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/chart_container.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/charts/chart_container.test.tsx @@ -5,30 +5,97 @@ */ import { render } from '@testing-library/react'; import React from 'react'; +import { FETCH_STATUS } from '../../../hooks/useFetcher'; import { ChartContainer } from './chart_container'; describe('ChartContainer', () => { - describe('when isLoading is true', () => { - it('shows loading the indicator', () => { - const component = render( - + describe('loading indicator', () => { + it('shows loading when status equals to Loading or Pending and has no data', () => { + [FETCH_STATUS.PENDING, FETCH_STATUS.LOADING].map((status) => { + const { queryAllByTestId } = render( + +
My amazing component
+
+ ); + + expect(queryAllByTestId('loading')[0]).toBeInTheDocument(); + }); + }); + it('does not show loading when status equals to Loading or Pending and has data', () => { + [FETCH_STATUS.PENDING, FETCH_STATUS.LOADING].map((status) => { + const { queryAllByText } = render( + +
My amazing component
+
+ ); + expect(queryAllByText('My amazing component')[0]).toBeInTheDocument(); + }); + }); + }); + + describe('failure indicator', () => { + it('shows failure message when status equals to Failure and has data', () => { + const { getByText } = render( +
My amazing component
); - - expect(component.getByTestId('loading')).toBeInTheDocument(); + expect( + getByText( + 'An error happened when trying to fetch data. Please try again' + ) + ).toBeInTheDocument(); + }); + it('shows failure message when status equals to Failure and has no data', () => { + const { getByText } = render( + +
My amazing component
+
+ ); + expect( + getByText( + 'An error happened when trying to fetch data. Please try again' + ) + ).toBeInTheDocument(); }); }); - describe('when isLoading is false', () => { - it('does not show the loading indicator', () => { - const component = render( - + describe('render component', () => { + it('shows children component when status Success and has data', () => { + const { getByText } = render( +
My amazing component
); - - expect(component.queryByTestId('loading')).not.toBeInTheDocument(); + expect(getByText('My amazing component')).toBeInTheDocument(); + }); + it('shows children component when status Success and has no data', () => { + const { getByText } = render( + +
My amazing component
+
+ ); + expect(getByText('My amazing component')).toBeInTheDocument(); }); }); }); diff --git a/x-pack/plugins/apm/public/components/shared/charts/chart_container.tsx b/x-pack/plugins/apm/public/components/shared/charts/chart_container.tsx index a6f579308597f..b4486f1e9b94a 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/chart_container.tsx +++ b/x-pack/plugins/apm/public/components/shared/charts/chart_container.tsx @@ -3,27 +3,56 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { EuiLoadingChart } from '@elastic/eui'; + +import { EuiLoadingChart, EuiText } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import React from 'react'; +import { FETCH_STATUS } from '../../../hooks/useFetcher'; interface Props { - isLoading: boolean; + hasData: boolean; + status: FETCH_STATUS; height: number; children: React.ReactNode; } -export function ChartContainer({ isLoading, children, height }: Props) { +export function ChartContainer({ children, height, status, hasData }: Props) { + if ( + !hasData && + (status === FETCH_STATUS.LOADING || status === FETCH_STATUS.PENDING) + ) { + return ; + } + + if (status === FETCH_STATUS.FAILURE) { + return ; + } + + return
{children}
; +} + +function LoadingChartPlaceholder({ height }: { height: number }) { return (
- {isLoading && } - {children} +
); } + +function FailedChartPlaceholder({ height }: { height: number }) { + return ( + + {i18n.translate('xpack.apm.chart.error', { + defaultMessage: + 'An error happened when trying to fetch data. Please try again', + })} + + ); +} diff --git a/x-pack/plugins/apm/public/components/shared/charts/erroneous_transactions_rate_chart/legacy.tsx b/x-pack/plugins/apm/public/components/shared/charts/erroneous_transactions_rate_chart/legacy.tsx deleted file mode 100644 index 29102f606414f..0000000000000 --- a/x-pack/plugins/apm/public/components/shared/charts/erroneous_transactions_rate_chart/legacy.tsx +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -import { EuiPanel, EuiSpacer, EuiTitle } from '@elastic/eui'; -import theme from '@elastic/eui/dist/eui_theme_light.json'; -import { i18n } from '@kbn/i18n'; -import { max } from 'lodash'; -import React, { useCallback } from 'react'; -import { useParams } from 'react-router-dom'; -import { asPercent } from '../../../../../common/utils/formatters'; -import { useLegacyChartsSync as useChartsSync } from '../../../../hooks/use_charts_sync'; -import { useFetcher } from '../../../../hooks/useFetcher'; -import { useUrlParams } from '../../../../hooks/useUrlParams'; -import { callApmApi } from '../../../../services/rest/createCallApmApi'; -// @ts-expect-error -import CustomPlot from '../CustomPlot'; - -const tickFormatY = (y?: number | null) => { - return asPercent(y || 0, 1); -}; - -/** - * "Legacy" version of this chart using react-vis charts. See index.tsx for the - * Elastic Charts version. - * - * This will be removed with #70290. - */ -export function ErroneousTransactionsRateChart() { - const { serviceName } = useParams<{ serviceName?: string }>(); - const { urlParams, uiFilters } = useUrlParams(); - const syncedChartsProps = useChartsSync(); - - const { start, end, transactionType, transactionName } = urlParams; - - const { data } = useFetcher(() => { - if (serviceName && start && end) { - return callApmApi({ - pathname: - '/api/apm/services/{serviceName}/transaction_groups/error_rate', - params: { - path: { - serviceName, - }, - query: { - start, - end, - transactionType, - transactionName, - uiFilters: JSON.stringify(uiFilters), - }, - }, - }); - } - }, [serviceName, start, end, uiFilters, transactionType, transactionName]); - - const combinedOnHover = useCallback( - (hoverX: number) => { - return syncedChartsProps.onHover(hoverX); - }, - [syncedChartsProps] - ); - - const errorRates = data?.transactionErrorRate || []; - const maxRate = max(errorRates.map((errorRate) => errorRate.y)); - - return ( - - - - {i18n.translate('xpack.apm.errorRateChart.title', { - defaultMessage: 'Transaction error rate', - })} - - - - - Number.isFinite(y) ? tickFormatY(y) : 'N/A' - } - /> - - ); -} diff --git a/x-pack/plugins/apm/public/components/shared/charts/line_chart/index.tsx b/x-pack/plugins/apm/public/components/shared/charts/line_chart/index.tsx index 3f2a08ecb7641..507acc49d89db 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/line_chart/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/charts/line_chart/index.tsx @@ -20,15 +20,17 @@ import moment from 'moment'; import React, { useEffect } from 'react'; import { useHistory } from 'react-router-dom'; import { TimeSeries } from '../../../../../typings/timeseries'; +import { FETCH_STATUS } from '../../../../hooks/useFetcher'; import { useUrlParams } from '../../../../hooks/useUrlParams'; import { useChartsSync } from '../../../../hooks/use_charts_sync'; import { unit } from '../../../../style/variables'; +import { Annotations } from '../annotations'; import { ChartContainer } from '../chart_container'; import { onBrushEnd } from '../helper/helper'; interface Props { id: string; - isLoading: boolean; + fetchStatus: FETCH_STATUS; onToggleLegend?: LegendItemListener; timeseries: TimeSeries[]; /** @@ -38,18 +40,20 @@ interface Props { /** * Formatter for legend and tooltip values */ - yTickFormat: (y: number) => string; + yTickFormat?: (y: number) => string; + showAnnotations?: boolean; } const XY_HEIGHT = unit * 16; export function LineChart({ id, - isLoading, + fetchStatus, onToggleLegend, timeseries, yLabelFormat, yTickFormat, + showAnnotations = true, }: Props) { const history = useHistory(); const chartRef = React.createRef(); @@ -84,7 +88,7 @@ export function LineChart({ ); return ( - + onBrushEnd({ x, history })} @@ -115,11 +119,13 @@ export function LineChart({ id="y-axis" ticks={3} position={Position.Left} - tickFormat={yTickFormat} + tickFormat={yTickFormat ? yTickFormat : yLabelFormat} labelFormat={yLabelFormat} showGridLines /> + {showAnnotations && } + {timeseries.map((serie) => { return ( (); const { urlParams, uiFilters } = useUrlParams(); @@ -56,25 +61,32 @@ export function ErroneousTransactionsRateChart() { const errorRates = data?.transactionErrorRate || []; return ( - + + +

+ {i18n.translate('xpack.apm.errorRate', { + defaultMessage: 'Error rate', + })} +

+
+ +
); } diff --git a/x-pack/plugins/apm/public/hooks/useTransactionBreakdown.ts b/x-pack/plugins/apm/public/hooks/useTransactionBreakdown.ts index 08d2300c3254a..0705383ecb0ca 100644 --- a/x-pack/plugins/apm/public/hooks/useTransactionBreakdown.ts +++ b/x-pack/plugins/apm/public/hooks/useTransactionBreakdown.ts @@ -15,7 +15,7 @@ export function useTransactionBreakdown() { uiFilters, } = useUrlParams(); - const { data = { timeseries: [] }, error, status } = useFetcher( + const { data = { timeseries: undefined }, error, status } = useFetcher( (callApmApi) => { if (serviceName && start && end && transactionType) { return callApmApi({ diff --git a/x-pack/plugins/apm/public/hooks/useTransactionDistribution.ts b/x-pack/plugins/apm/public/hooks/useTransactionDistribution.ts index a5096a314388c..8c76225d03486 100644 --- a/x-pack/plugins/apm/public/hooks/useTransactionDistribution.ts +++ b/x-pack/plugins/apm/public/hooks/useTransactionDistribution.ts @@ -10,7 +10,7 @@ import { IUrlParams } from '../context/UrlParamsContext/types'; import { useFetcher } from './useFetcher'; import { useUiFilters } from '../context/UrlParamsContext'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { TransactionDistributionAPIResponse } from '../../server/lib/transactions/distribution'; +import type { TransactionDistributionAPIResponse } from '../../server/lib/transactions/distribution'; import { toQuery, fromQuery } from '../components/shared/Links/url_helpers'; import { maybe } from '../../common/utils/maybe'; diff --git a/x-pack/plugins/apm/public/hooks/useTransactionList.ts b/x-pack/plugins/apm/public/hooks/useTransactionList.ts index 9c3a18b9c0d0d..b2c2cc30f78ec 100644 --- a/x-pack/plugins/apm/public/hooks/useTransactionList.ts +++ b/x-pack/plugins/apm/public/hooks/useTransactionList.ts @@ -14,8 +14,8 @@ type TransactionsAPIResponse = APIReturnType< '/api/apm/services/{serviceName}/transaction_groups' >; -const DEFAULT_RESPONSE: TransactionsAPIResponse = { - items: [], +const DEFAULT_RESPONSE: Partial = { + items: undefined, isAggregationAccurate: true, bucketSize: 0, }; diff --git a/x-pack/plugins/apm/public/hooks/use_annotations.ts b/x-pack/plugins/apm/public/hooks/use_annotations.ts new file mode 100644 index 0000000000000..2b1c2bec52b3d --- /dev/null +++ b/x-pack/plugins/apm/public/hooks/use_annotations.ts @@ -0,0 +1,38 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { useParams } from 'react-router-dom'; +import { callApmApi } from '../services/rest/createCallApmApi'; +import { useFetcher } from './useFetcher'; +import { useUrlParams } from './useUrlParams'; + +const INITIAL_STATE = { annotations: [] }; + +export function useAnnotations() { + const { serviceName } = useParams<{ serviceName?: string }>(); + const { urlParams, uiFilters } = useUrlParams(); + const { start, end } = urlParams; + const { environment } = uiFilters; + + const { data = INITIAL_STATE } = useFetcher(() => { + if (start && end && serviceName) { + return callApmApi({ + pathname: '/api/apm/services/{serviceName}/annotation/search', + params: { + path: { + serviceName, + }, + query: { + start, + end, + environment, + }, + }, + }); + } + }, [start, end, environment, serviceName]); + + return data; +} diff --git a/x-pack/plugins/apm/public/selectors/chartSelectors.ts b/x-pack/plugins/apm/public/selectors/chartSelectors.ts index 8c6093859f969..450f02f70c6a4 100644 --- a/x-pack/plugins/apm/public/selectors/chartSelectors.ts +++ b/x-pack/plugins/apm/public/selectors/chartSelectors.ts @@ -31,40 +31,37 @@ export interface ITpmBucket { } export interface ITransactionChartData { - tpmSeries: ITpmBucket[]; - responseTimeSeries: TimeSeries[]; + tpmSeries?: ITpmBucket[]; + responseTimeSeries?: TimeSeries[]; mlJobId: string | undefined; } -const INITIAL_DATA = { - apmTimeseries: { - responseTimes: { - avg: [], - p95: [], - p99: [], - }, - tpmBuckets: [], - overallAvgDuration: null, - }, +const INITIAL_DATA: Partial = { + apmTimeseries: undefined, anomalyTimeseries: undefined, }; export function getTransactionCharts( { transactionType }: IUrlParams, - { apmTimeseries, anomalyTimeseries }: TimeSeriesAPIResponse = INITIAL_DATA + charts = INITIAL_DATA ): ITransactionChartData { - const tpmSeries = getTpmSeries(apmTimeseries, transactionType); - - const responseTimeSeries = getResponseTimeSeries({ - apmTimeseries, - anomalyTimeseries, - }); + const { apmTimeseries, anomalyTimeseries } = charts; - return { - tpmSeries, - responseTimeSeries, + const transactionCharts: ITransactionChartData = { + tpmSeries: undefined, + responseTimeSeries: undefined, mlJobId: anomalyTimeseries?.jobId, }; + + if (apmTimeseries) { + transactionCharts.tpmSeries = getTpmSeries(apmTimeseries, transactionType); + + transactionCharts.responseTimeSeries = getResponseTimeSeries({ + apmTimeseries, + anomalyTimeseries, + }); + } + return transactionCharts; } export function getResponseTimeSeries({ 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 a42710947a792..b12dd73a20986 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 @@ -73,6 +73,6 @@ export async function getBuckets({ return { noHits: resp.hits.total.value === 0, - buckets, + buckets: resp.hits.total.value > 0 ? buckets : [], }; } 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 2bfd3c94ed34c..9020cb1b9953a 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 @@ -7,14 +7,16 @@ import { ValuesType } from 'utility-types'; import { APMBaseDoc } from '../../../../../typings/es_schemas/raw/apm_base_doc'; import { APMError } from '../../../../../typings/es_schemas/ui/apm_error'; -import { KibanaRequest } from '../../../../../../../../src/core/server'; +import { + KibanaRequest, + LegacyScopedClusterClient, +} from '../../../../../../../../src/core/server'; import { ProcessorEvent } from '../../../../../common/processor_event'; import { ESSearchRequest, ESSearchResponse, } from '../../../../../typings/elasticsearch'; import { ApmIndicesConfig } from '../../../settings/apm_indices/get_apm_indices'; -import { APMRequestHandlerContext } from '../../../../routes/typings'; import { addFilterToExcludeLegacyData } from './add_filter_to_exclude_legacy_data'; import { callClientWithDebug } from '../call_client_with_debug'; import { Transaction } from '../../../../../typings/es_schemas/ui/transaction'; @@ -51,20 +53,23 @@ type TypedSearchResponse< export type APMEventClient = ReturnType; export function createApmEventClient({ - context, + esClient, + debug, request, indices, options: { includeFrozen } = { includeFrozen: false }, }: { - context: APMRequestHandlerContext; + esClient: Pick< + LegacyScopedClusterClient, + 'callAsInternalUser' | 'callAsCurrentUser' + >; + debug: boolean; request: KibanaRequest; indices: ApmIndicesConfig; options: { includeFrozen: boolean; }; }) { - const client = context.core.elasticsearch.legacy.client; - return { search( params: TParams, @@ -77,14 +82,14 @@ export function createApmEventClient({ : withProcessorEventFilter; return callClientWithDebug({ - apiCaller: client.callAsCurrentUser, + apiCaller: esClient.callAsCurrentUser, operationName: 'search', params: { ...withPossibleLegacyDataFilter, ignore_throttled: !includeFrozen, }, request, - debug: context.params.query._debug, + debug, }); }, }; diff --git a/x-pack/plugins/apm/server/lib/helpers/setup_request.ts b/x-pack/plugins/apm/server/lib/helpers/setup_request.ts index 5e75535c678b3..363c4128137e0 100644 --- a/x-pack/plugins/apm/server/lib/helpers/setup_request.ts +++ b/x-pack/plugins/apm/server/lib/helpers/setup_request.ts @@ -88,7 +88,8 @@ export async function setupRequest( const coreSetupRequest = { indices, apmEventClient: createApmEventClient({ - context, + esClient: context.core.elasticsearch.legacy.client, + debug: context.params.query._debug, request, indices, options: { includeFrozen }, diff --git a/x-pack/plugins/apm/server/plugin.ts b/x-pack/plugins/apm/server/plugin.ts index d3341b6c1b163..44269b1775953 100644 --- a/x-pack/plugins/apm/server/plugin.ts +++ b/x-pack/plugins/apm/server/plugin.ts @@ -10,14 +10,17 @@ import { map, take } from 'rxjs/operators'; import { CoreSetup, CoreStart, + KibanaRequest, Logger, Plugin, PluginInitializerContext, + RequestHandlerContext, } from 'src/core/server'; import { APMConfig, APMXPackConfig, mergeConfigs } from '.'; import { APMOSSPluginSetup } from '../../../../src/plugins/apm_oss/server'; import { HomeServerPluginSetup } from '../../../../src/plugins/home/server'; import { UsageCollectionSetup } from '../../../../src/plugins/usage_collection/server'; +import { UI_SETTINGS } from '../../../../src/plugins/data/common'; import { ActionsPlugin } from '../../actions/server'; import { AlertingPlugin } from '../../alerts/server'; import { CloudSetup } from '../../cloud/server'; @@ -30,6 +33,7 @@ import { TaskManagerSetupContract } from '../../task_manager/server'; import { APM_FEATURE, registerFeaturesUsage } from './feature'; import { registerApmAlerts } from './lib/alerts/register_apm_alerts'; import { createApmTelemetry } from './lib/apm_telemetry'; +import { createApmEventClient } from './lib/helpers/create_es_client/create_apm_event_client'; import { getInternalSavedObjectsClient } from './lib/helpers/get_internal_saved_objects_client'; import { createApmAgentConfigurationIndex } from './lib/settings/agent_configuration/create_agent_config_index'; import { getApmIndices } from './lib/settings/apm_indices/get_apm_indices'; @@ -42,6 +46,11 @@ import { uiSettings } from './ui_settings'; export interface APMPluginSetup { config$: Observable; getApmIndices: () => ReturnType; + createApmEventClient: (params: { + debug?: boolean; + request: KibanaRequest; + context: RequestHandlerContext; + }) => Promise>; } export class APMPlugin implements Plugin { @@ -141,13 +150,41 @@ export class APMPlugin implements Plugin { }, }); + const boundGetApmIndices = async () => + getApmIndices({ + savedObjectsClient: await getInternalSavedObjectsClient(core), + config: await mergedConfig$.pipe(take(1)).toPromise(), + }); + return { config$: mergedConfig$, - getApmIndices: async () => - getApmIndices({ - savedObjectsClient: await getInternalSavedObjectsClient(core), - config: await mergedConfig$.pipe(take(1)).toPromise(), - }), + getApmIndices: boundGetApmIndices, + createApmEventClient: async ({ + request, + context, + debug, + }: { + debug?: boolean; + request: KibanaRequest; + context: RequestHandlerContext; + }) => { + const [indices, includeFrozen] = await Promise.all([ + boundGetApmIndices(), + context.core.uiSettings.client.get(UI_SETTINGS.SEARCH_INCLUDE_FROZEN), + ]); + + const esClient = context.core.elasticsearch.legacy.client; + + return createApmEventClient({ + debug: debug ?? false, + esClient, + request, + indices, + options: { + includeFrozen, + }, + }); + }, }; } diff --git a/x-pack/plugins/canvas/types/state.ts b/x-pack/plugins/canvas/types/state.ts index 60407b78ab5e3..03bb931dc9b26 100644 --- a/x-pack/plugins/canvas/types/state.ts +++ b/x-pack/plugins/canvas/types/state.ts @@ -4,12 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ +import { KibanaContext } from 'src/plugins/data/common'; import { Datatable, ExpressionValueFilter, ExpressionImage, ExpressionFunction, - KibanaContext, PointSeries, Render, Style, diff --git a/x-pack/plugins/data_enhanced/common/search/es_search/es_search_rxjs_utils.ts b/x-pack/plugins/data_enhanced/common/search/es_search/es_search_rxjs_utils.ts index 2d5d09fd0205e..f38bec6d1f59f 100644 --- a/x-pack/plugins/data_enhanced/common/search/es_search/es_search_rxjs_utils.ts +++ b/x-pack/plugins/data_enhanced/common/search/es_search/es_search_rxjs_utils.ts @@ -8,11 +8,11 @@ import { of, merge, timer, throwError } from 'rxjs'; import { takeWhile, switchMap, expand, mergeMap, tap } from 'rxjs/operators'; import { - AbortError, doSearch, IKibanaSearchResponse, isErrorResponse, } from '../../../../../../src/plugins/data/common'; +import { AbortError } from '../../../../../../src/plugins/kibana_utils/common'; import type { IKibanaSearchRequest } from '../../../../../../src/plugins/data/common'; import type { IAsyncSearchOptions } from '../../../common/search/types'; diff --git a/x-pack/plugins/data_enhanced/public/search/search_interceptor.test.ts b/x-pack/plugins/data_enhanced/public/search/search_interceptor.test.ts index f47d2b39a89a9..044489d58eb0e 100644 --- a/x-pack/plugins/data_enhanced/public/search/search_interceptor.test.ts +++ b/x-pack/plugins/data_enhanced/public/search/search_interceptor.test.ts @@ -7,7 +7,8 @@ import type { MockedKeys } from '@kbn/utility-types/jest'; import { coreMock } from '../../../../../src/core/public/mocks'; import { EnhancedSearchInterceptor } from './search_interceptor'; import { CoreSetup, CoreStart } from 'kibana/public'; -import { AbortError, UI_SETTINGS } from '../../../../../src/plugins/data/common'; +import { UI_SETTINGS } from '../../../../../src/plugins/data/common'; +import { AbortError } from '../../../../../src/plugins/kibana_utils/public'; import { SearchTimeoutError } from 'src/plugins/data/public'; import { dataPluginMock } from '../../../../../src/plugins/data/public/mocks'; diff --git a/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts b/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts index 4cafcdb29ae8d..d36741ae6576d 100644 --- a/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts +++ b/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts @@ -13,7 +13,7 @@ import { SearchInterceptorDeps, UI_SETTINGS, } from '../../../../../src/plugins/data/public'; -import { AbortError, toPromise } from '../../../../../src/plugins/data/common'; +import { AbortError, abortSignalToPromise } from '../../../../../src/plugins/kibana_utils/public'; import { IAsyncSearchRequest, @@ -70,7 +70,7 @@ export class EnhancedSearchInterceptor extends SearchInterceptor { abortSignal: options.abortSignal, timeout: this.searchTimeout, }); - const abortedPromise = toPromise(combinedSignal); + const abortedPromise = abortSignalToPromise(combinedSignal); const strategy = options?.strategy ?? ENHANCED_ES_SEARCH_STRATEGY; this.pendingCount$.next(this.pendingCount$.getValue() + 1); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/constants.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/constants.ts index decf1e2158744..ea4906ec08946 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/constants.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/constants.ts @@ -3,8 +3,14 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ + import { i18n } from '@kbn/i18n'; +export const CREDENTIALS_TITLE = i18n.translate( + 'xpack.enterpriseSearch.appSearch.credentials.title', + { defaultMessage: 'Credentials' } +); + export enum ApiTokenTypes { Admin = 'admin', Private = 'private', diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials.tsx index c8eae8cc13f5f..72b02dfdc1f61 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials.tsx @@ -28,6 +28,7 @@ import { FlashMessages } from '../../../shared/flash_messages'; import { CredentialsLogic } from './credentials_logic'; import { externalUrl } from '../../../shared/enterprise_search_url/external_url'; +import { CREDENTIALS_TITLE } from './constants'; import { CredentialsList } from './credentials_list'; import { CredentialsFlyout } from './credentials_flyout'; @@ -47,21 +48,11 @@ export const Credentials: React.FC = () => { return ( <> - + -

- {i18n.translate('xpack.enterpriseSearch.appSearch.credentials.title', { - defaultMessage: 'Credentials', - })} -

+

{CREDENTIALS_TITLE}

diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/index.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/index.ts index bceda234175a7..0fc64a43ffa85 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/index.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/index.ts @@ -5,3 +5,4 @@ */ export { Credentials } from './credentials'; +export { CREDENTIALS_TITLE } from './constants'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/constants.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/constants.ts index ee5b47eda490e..3c963e415f33b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/constants.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/constants.ts @@ -9,10 +9,6 @@ import { i18n } from '@kbn/i18n'; // TODO: It's very likely that we'll move these i18n constants to their respective component // folders once those are migrated over. This is a temporary way of DRYing them out for now. -export const ENGINES_TITLE = i18n.translate('xpack.enterpriseSearch.appSearch.engines.title', { - defaultMessage: 'Engines', -}); - export const OVERVIEW_TITLE = i18n.translate( 'xpack.enterpriseSearch.appSearch.engine.overview.title', { defaultMessage: 'Overview' } diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_nav.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_nav.tsx index e5ee392b34c01..f92fefc7124b8 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_nav.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_nav.tsx @@ -30,8 +30,8 @@ import { ENGINE_API_LOGS_PATH, } from '../../routes'; import { getAppSearchUrl } from '../../../shared/enterprise_search_url'; +import { ENGINES_TITLE } from '../engines'; import { - ENGINES_TITLE, OVERVIEW_TITLE, ANALYTICS_TITLE, DOCUMENTS_TITLE, diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/assets/engine_icon.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/assets/engine_icon.tsx similarity index 100% rename from x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/assets/engine_icon.tsx rename to x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/assets/engine_icon.tsx diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/assets/meta_engine_icon.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/assets/meta_engine_icon.tsx similarity index 100% rename from x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/assets/meta_engine_icon.tsx rename to x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/assets/meta_engine_icon.tsx diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/empty_state.scss b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_state.scss similarity index 100% rename from x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/empty_state.scss rename to x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_state.scss diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/empty_state.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_state.test.tsx similarity index 100% rename from x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/empty_state.test.tsx rename to x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_state.test.tsx diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/empty_state.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_state.tsx similarity index 96% rename from x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/empty_state.tsx rename to x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_state.tsx index b7ed1cc895097..95142782d2272 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/empty_state.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_state.tsx @@ -14,7 +14,7 @@ import { getAppSearchUrl } from '../../../../shared/enterprise_search_url'; import { SetAppSearchChrome as SetPageChrome } from '../../../../shared/kibana_chrome'; import { CREATE_ENGINES_PATH } from '../../../routes'; -import { EngineOverviewHeader } from './header'; +import { EnginesOverviewHeader } from './header'; import './empty_state.scss'; @@ -34,7 +34,7 @@ export const EmptyState: React.FC = () => { return ( <> - + { +describe('EnginesOverviewHeader', () => { it('renders', () => { - const wrapper = shallow(); + const wrapper = shallow(); expect(wrapper.find('h1')).toHaveLength(1); }); it('renders a launch app search button that sends telemetry on click', () => { - const wrapper = shallow(); + const wrapper = shallow(); const button = wrapper.find('[data-test-subj="launchButton"]'); expect(button.prop('href')).toBe('http://localhost:3002/as'); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/header.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/header.tsx similarity index 93% rename from x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/header.tsx rename to x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/header.tsx index 4bb69bafa0996..3faa74be11e98 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/header.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/header.tsx @@ -19,7 +19,7 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { TelemetryLogic } from '../../../../shared/telemetry'; import { getAppSearchUrl } from '../../../../shared/enterprise_search_url'; -export const EngineOverviewHeader: React.FC = () => { +export const EnginesOverviewHeader: React.FC = () => { const { sendAppSearchTelemetry } = useActions(TelemetryLogic); const buttonProps = { @@ -42,7 +42,7 @@ export const EngineOverviewHeader: React.FC = () => {

diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/index.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/index.ts similarity index 87% rename from x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/index.ts rename to x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/index.ts index 794053f184f8c..cb2e0f825d455 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/index.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/index.ts @@ -4,6 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -export { EngineOverviewHeader } from './header'; +export { EnginesOverviewHeader } from './header'; export { LoadingState } from './loading_state'; export { EmptyState } from './empty_state'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/loading_state.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/loading_state.test.tsx similarity index 100% rename from x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/loading_state.test.tsx rename to x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/loading_state.test.tsx diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/loading_state.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/loading_state.tsx similarity index 89% rename from x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/loading_state.tsx rename to x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/loading_state.tsx index 832a133ed43c7..8e2166d2ef105 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/loading_state.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/loading_state.tsx @@ -8,13 +8,13 @@ import React from 'react'; import { EuiPageContent, EuiSpacer, EuiLoadingContent } from '@elastic/eui'; import { SetAppSearchChrome as SetPageChrome } from '../../../../shared/kibana_chrome'; -import { EngineOverviewHeader } from './header'; +import { EnginesOverviewHeader } from './header'; export const LoadingState: React.FC = () => { return ( <> - + diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/constants.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/constants.ts new file mode 100644 index 0000000000000..12545c59b40a0 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/constants.ts @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { i18n } from '@kbn/i18n'; + +export const ENGINES_TITLE = i18n.translate('xpack.enterpriseSearch.appSearch.engines.title', { + defaultMessage: 'Engines', +}); + +export const META_ENGINES_TITLE = i18n.translate( + 'xpack.enterpriseSearch.appSearch.metaEngines.title', + { defaultMessage: 'Meta Engines' } +); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview.scss b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.scss similarity index 96% rename from x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview.scss rename to x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.scss index 5e8a20ba425ad..c956f3da562f6 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview.scss +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.scss @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -.engineOverview { +.enginesOverview { padding: $euiSize; @include euiBreakpoint('m', 'l', 'xl') { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.test.tsx similarity index 80% rename from x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview.test.tsx rename to x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.test.tsx index f87ea2d422780..61f783a8b6c2e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.test.tsx @@ -14,14 +14,14 @@ import { shallow, ReactWrapper } from 'enzyme'; import { mountAsync, mockHttpValues, setMockValues } from '../../../__mocks__'; import { LoadingState, EmptyState } from './components'; -import { EngineTable } from './engine_table'; +import { EnginesTable } from './engines_table'; -import { EngineOverview } from './'; +import { EnginesOverview } from './'; -describe('EngineOverview', () => { +describe('EnginesOverview', () => { describe('non-happy-path states', () => { it('isLoading', () => { - const wrapper = shallow(); + const wrapper = shallow(); expect(wrapper.find(LoadingState)).toHaveLength(1); }); @@ -36,7 +36,7 @@ describe('EngineOverview', () => { }), }, }); - const wrapper = await mountAsync(, { i18n: true }); + const wrapper = await mountAsync(, { i18n: true }); expect(wrapper.find(EmptyState)).toHaveLength(1); }); @@ -69,9 +69,9 @@ describe('EngineOverview', () => { }); it('renders and calls the engines API', async () => { - const wrapper = await mountAsync(, { i18n: true }); + const wrapper = await mountAsync(, { i18n: true }); - expect(wrapper.find(EngineTable)).toHaveLength(1); + expect(wrapper.find(EnginesTable)).toHaveLength(1); expect(mockApi).toHaveBeenNthCalledWith(1, '/api/app_search/engines', { query: { type: 'indexed', @@ -86,9 +86,9 @@ describe('EngineOverview', () => { hasPlatinumLicense: true, http: { ...mockHttpValues.http, get: mockApi }, }); - const wrapper = await mountAsync(, { i18n: true }); + const wrapper = await mountAsync(, { i18n: true }); - expect(wrapper.find(EngineTable)).toHaveLength(2); + expect(wrapper.find(EnginesTable)).toHaveLength(2); expect(mockApi).toHaveBeenNthCalledWith(2, '/api/app_search/engines', { query: { type: 'meta', @@ -100,10 +100,10 @@ describe('EngineOverview', () => { describe('pagination', () => { const getTablePagination = (wrapper: ReactWrapper) => - wrapper.find(EngineTable).prop('pagination'); + wrapper.find(EnginesTable).prop('pagination'); it('passes down page data from the API', async () => { - const wrapper = await mountAsync(, { i18n: true }); + const wrapper = await mountAsync(, { i18n: true }); const pagination = getTablePagination(wrapper); expect(pagination.totalEngines).toEqual(100); @@ -111,7 +111,7 @@ describe('EngineOverview', () => { }); it('re-polls the API on page change', async () => { - const wrapper = await mountAsync(, { i18n: true }); + const wrapper = await mountAsync(, { i18n: true }); await act(async () => getTablePagination(wrapper).onPaginate(5)); wrapper.update(); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.tsx similarity index 83% rename from x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview.tsx rename to x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.tsx index c0fd254567910..559fef695d63b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.tsx @@ -13,7 +13,6 @@ import { EuiTitle, EuiSpacer, } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; import { SendAppSearchTelemetry as SendTelemetry } from '../../../shared/telemetry'; @@ -23,11 +22,11 @@ import { LicensingLogic } from '../../../shared/licensing'; import { EngineIcon } from './assets/engine_icon'; import { MetaEngineIcon } from './assets/meta_engine_icon'; +import { ENGINES_TITLE, META_ENGINES_TITLE } from './constants'; +import { EnginesOverviewHeader, LoadingState, EmptyState } from './components'; +import { EnginesTable } from './engines_table'; -import { EngineOverviewHeader, LoadingState, EmptyState } from './components'; -import { EngineTable } from './engine_table'; - -import './engine_overview.scss'; +import './engines_overview.scss'; interface IGetEnginesParams { type: string; @@ -38,7 +37,7 @@ interface ISetEnginesCallbacks { setResultsTotal: React.Dispatch>; } -export const EngineOverview: React.FC = () => { +export const EnginesOverview: React.FC = () => { const { http } = useValues(HttpLogic); const { hasPlatinumLicense } = useValues(LicensingLogic); @@ -88,21 +87,18 @@ export const EngineOverview: React.FC = () => { - - + +

- - {i18n.translate('xpack.enterpriseSearch.appSearch.enginesOverview.engines', { - defaultMessage: 'Engines', - })} + {ENGINES_TITLE}

- {

- - {i18n.translate('xpack.enterpriseSearch.appSearch.enginesOverview.metaEngines', { - defaultMessage: 'Meta Engines', - })} + {META_ENGINES_TITLE}

- { +describe('EnginesTable', () => { const onPaginate = jest.fn(); // onPaginate updates the engines API call upstream const wrapper = mountWithIntl( - { it('handles empty data', () => { const emptyWrapper = mountWithIntl( - {} }} /> + {} }} + /> ); const emptyTable = emptyWrapper.find(EuiBasicTable); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_table.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_table.tsx similarity index 92% rename from x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_table.tsx rename to x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_table.tsx index abeaf45e6aee8..a9cf64b3dffda 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_table.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_table.tsx @@ -16,28 +16,28 @@ import { getEngineRoute } from '../../routes'; import { ENGINES_PAGE_SIZE } from '../../../../../common/constants'; -export interface IEngineTableData { +interface IEnginesTableData { name: string; created_at: string; document_count: number; field_count: number; } -export interface IEngineTablePagination { +interface IEnginesTablePagination { totalEngines: number; pageIndex: number; onPaginate(pageIndex: number): void; } -export interface IEngineTableProps { - data: IEngineTableData[]; - pagination: IEngineTablePagination; +interface IEnginesTableProps { + data: IEnginesTableData[]; + pagination: IEnginesTablePagination; } -export interface IOnChange { +interface IOnChange { page: { index: number; }; } -export const EngineTable: React.FC = ({ +export const EnginesTable: React.FC = ({ data, pagination: { totalEngines, pageIndex, onPaginate }, }) => { @@ -52,7 +52,7 @@ export const EngineTable: React.FC = ({ }), }); - const columns: Array> = [ + const columns: Array> = [ { field: 'name', name: i18n.translate('xpack.enterpriseSearch.appSearch.enginesOverview.table.column.name', { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/index.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/index.ts new file mode 100644 index 0000000000000..76ca9239a3c7e --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { EnginesOverview } from './engines_overview'; +export { ENGINES_TITLE, META_ENGINES_TITLE } from './constants'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/constants.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/constants.ts new file mode 100644 index 0000000000000..133d8b604381b --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/constants.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; + * you may not use this file except in compliance with the Elastic License. + */ + +import { i18n } from '@kbn/i18n'; + +export const ROLE_MAPPINGS_TITLE = i18n.translate( + 'xpack.enterpriseSearch.appSearch.roleMappings.title', + { defaultMessage: 'Role Mappings' } +); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/index.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/index.ts similarity index 82% rename from x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/index.ts rename to x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/index.ts index 48b7645dc39e8..662b91bb3e925 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/index.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/index.ts @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export { EngineOverview } from './engine_overview'; +export { ROLE_MAPPINGS_TITLE } from './constants'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/constants.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/constants.ts new file mode 100644 index 0000000000000..c7b22d740341c --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/constants.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { i18n } from '@kbn/i18n'; + +export const SETTINGS_TITLE = i18n.translate('xpack.enterpriseSearch.appSearch.settings.title', { + defaultMessage: 'Settings', +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/index.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/index.ts index db74dcb1a1846..3e162a4a2a1bc 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/index.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/index.ts @@ -5,3 +5,4 @@ */ export { Settings } from './settings'; +export { SETTINGS_TITLE } from './constants'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts new file mode 100644 index 0000000000000..367c7b085123f --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts @@ -0,0 +1,368 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { resetContext } from 'kea'; + +import { mockHttpValues } from '../../../../__mocks__'; +jest.mock('../../../../shared/http', () => ({ + HttpLogic: { values: mockHttpValues }, +})); +const { http } = mockHttpValues; + +jest.mock('../../../../shared/flash_messages', () => ({ + flashAPIErrors: jest.fn(), +})); +import { flashAPIErrors } from '../../../../shared/flash_messages'; + +import { ELogRetentionOptions } from './types'; +import { LogRetentionLogic } from './log_retention_logic'; + +describe('LogRetentionLogic', () => { + const TYPICAL_SERVER_LOG_RETENTION = { + analytics: { + disabled_at: null, + enabled: true, + retention_policy: { is_default: true, min_age_days: 180 }, + }, + api: { + disabled_at: null, + enabled: true, + retention_policy: { is_default: true, min_age_days: 180 }, + }, + }; + + const TYPICAL_CLIENT_LOG_RETENTION = { + analytics: { + disabledAt: null, + enabled: true, + retentionPolicy: { isDefault: true, minAgeDays: 180 }, + }, + api: { + disabledAt: null, + enabled: true, + retentionPolicy: { isDefault: true, minAgeDays: 180 }, + }, + }; + + const DEFAULT_VALUES = { + logRetention: null, + openedModal: null, + isLogRetentionUpdating: false, + }; + + const mount = (defaults?: object) => { + if (!defaults) { + resetContext({}); + } else { + resetContext({ + defaults: { + enterprise_search: { + app_search: { + log_retention_logic: { + ...defaults, + }, + }, + }, + }, + }); + } + LogRetentionLogic.mount(); + }; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('has expected default values', () => { + mount(); + expect(LogRetentionLogic.values).toEqual(DEFAULT_VALUES); + }); + + describe('actions', () => { + describe('setOpenedModal', () => { + describe('openedModal', () => { + it('should be set to the provided value', () => { + mount(); + + LogRetentionLogic.actions.setOpenedModal(ELogRetentionOptions.Analytics); + + expect(LogRetentionLogic.values).toEqual({ + ...DEFAULT_VALUES, + openedModal: ELogRetentionOptions.Analytics, + }); + }); + }); + }); + + describe('closeModals', () => { + describe('openedModal', () => { + it('resets openedModal to null', () => { + mount({ + openedModal: 'analytics', + }); + + LogRetentionLogic.actions.closeModals(); + + expect(LogRetentionLogic.values).toEqual({ + ...DEFAULT_VALUES, + openedModal: null, + }); + }); + }); + + describe('isLogRetentionUpdating', () => { + it('resets isLogRetentionUpdating to false', () => { + mount({ + isLogRetentionUpdating: true, + }); + + LogRetentionLogic.actions.closeModals(); + + expect(LogRetentionLogic.values).toEqual({ + ...DEFAULT_VALUES, + isLogRetentionUpdating: false, + }); + }); + }); + }); + + describe('clearLogRetentionUpdating', () => { + describe('isLogRetentionUpdating', () => { + it('resets isLogRetentionUpdating to false', () => { + mount({ + isLogRetentionUpdating: true, + }); + + LogRetentionLogic.actions.clearLogRetentionUpdating(); + + expect(LogRetentionLogic.values).toEqual({ + ...DEFAULT_VALUES, + isLogRetentionUpdating: false, + }); + }); + }); + }); + + describe('updateLogRetention', () => { + describe('logRetention', () => { + it('updates the logRetention values that are passed', () => { + mount({ + logRetention: {}, + }); + + LogRetentionLogic.actions.updateLogRetention({ + api: { + disabledAt: null, + enabled: true, + retentionPolicy: null, + }, + analytics: { + disabledAt: null, + enabled: true, + retentionPolicy: null, + }, + }); + + expect(LogRetentionLogic.values).toEqual({ + ...DEFAULT_VALUES, + logRetention: { + api: { + disabledAt: null, + enabled: true, + retentionPolicy: null, + }, + analytics: { + disabledAt: null, + enabled: true, + retentionPolicy: null, + }, + }, + }); + }); + }); + }); + + describe('saveLogRetention', () => { + beforeEach(() => { + mount(); + jest.spyOn(LogRetentionLogic.actions, 'clearLogRetentionUpdating'); + }); + + describe('openedModal', () => { + it('should be reset to null', () => { + mount({ + openedModal: ELogRetentionOptions.Analytics, + }); + + LogRetentionLogic.actions.saveLogRetention(ELogRetentionOptions.Analytics, true); + + expect(LogRetentionLogic.values).toEqual({ + ...DEFAULT_VALUES, + openedModal: null, + }); + }); + }); + + it('will call an API endpoint and update log retention', async () => { + jest.spyOn(LogRetentionLogic.actions, 'updateLogRetention'); + const promise = Promise.resolve(TYPICAL_SERVER_LOG_RETENTION); + http.put.mockReturnValue(promise); + + LogRetentionLogic.actions.saveLogRetention(ELogRetentionOptions.Analytics, true); + + expect(http.put).toHaveBeenCalledWith('/api/app_search/log_settings', { + body: JSON.stringify({ + analytics: { + enabled: true, + }, + }), + }); + + await promise; + expect(LogRetentionLogic.actions.updateLogRetention).toHaveBeenCalledWith( + TYPICAL_CLIENT_LOG_RETENTION + ); + + expect(LogRetentionLogic.actions.clearLogRetentionUpdating).toHaveBeenCalled(); + }); + + it('handles errors', async () => { + const promise = Promise.reject('An error occured'); + http.put.mockReturnValue(promise); + + LogRetentionLogic.actions.saveLogRetention(ELogRetentionOptions.Analytics, true); + + try { + await promise; + } catch { + // Do nothing + } + expect(flashAPIErrors).toHaveBeenCalledWith('An error occured'); + expect(LogRetentionLogic.actions.clearLogRetentionUpdating).toHaveBeenCalled(); + }); + }); + + describe('toggleLogRetention', () => { + describe('isLogRetentionUpdating', () => { + it('sets isLogRetentionUpdating to true', () => { + mount({ + isLogRetentionUpdating: false, + }); + + LogRetentionLogic.actions.toggleLogRetention(ELogRetentionOptions.Analytics); + + expect(LogRetentionLogic.values).toEqual({ + ...DEFAULT_VALUES, + isLogRetentionUpdating: true, + }); + }); + }); + + it('will call setOpenedModal if already enabled', () => { + mount({ + logRetention: { + [ELogRetentionOptions.Analytics]: { + enabled: true, + }, + }, + }); + jest.spyOn(LogRetentionLogic.actions, 'setOpenedModal'); + + LogRetentionLogic.actions.toggleLogRetention(ELogRetentionOptions.Analytics); + + expect(LogRetentionLogic.actions.setOpenedModal).toHaveBeenCalledWith( + ELogRetentionOptions.Analytics + ); + }); + }); + + describe('fetchLogRetention', () => { + describe('isLogRetentionUpdating', () => { + it('sets isLogRetentionUpdating to true', () => { + mount({ + isLogRetentionUpdating: false, + }); + + LogRetentionLogic.actions.fetchLogRetention(); + + expect(LogRetentionLogic.values).toEqual({ + ...DEFAULT_VALUES, + isLogRetentionUpdating: true, + }); + }); + }); + + it('will call an API endpoint and update log retention', async () => { + mount(); + jest.spyOn(LogRetentionLogic.actions, 'clearLogRetentionUpdating'); + jest + .spyOn(LogRetentionLogic.actions, 'updateLogRetention') + .mockImplementationOnce(() => {}); + + const promise = Promise.resolve(TYPICAL_SERVER_LOG_RETENTION); + http.get.mockReturnValue(promise); + + LogRetentionLogic.actions.fetchLogRetention(); + + expect(http.get).toHaveBeenCalledWith('/api/app_search/log_settings'); + await promise; + expect(LogRetentionLogic.actions.updateLogRetention).toHaveBeenCalledWith( + TYPICAL_CLIENT_LOG_RETENTION + ); + + expect(LogRetentionLogic.actions.clearLogRetentionUpdating).toHaveBeenCalled(); + }); + + it('handles errors', async () => { + mount(); + jest.spyOn(LogRetentionLogic.actions, 'clearLogRetentionUpdating'); + const promise = Promise.reject('An error occured'); + http.get.mockReturnValue(promise); + + LogRetentionLogic.actions.fetchLogRetention(); + + try { + await promise; + } catch { + // Do nothing + } + expect(flashAPIErrors).toHaveBeenCalledWith('An error occured'); + expect(LogRetentionLogic.actions.clearLogRetentionUpdating).toHaveBeenCalled(); + }); + }); + + it('will call saveLogRetention if NOT already enabled', () => { + mount({ + logRetention: { + [ELogRetentionOptions.Analytics]: { + enabled: false, + }, + }, + }); + jest.spyOn(LogRetentionLogic.actions, 'saveLogRetention'); + + LogRetentionLogic.actions.toggleLogRetention(ELogRetentionOptions.Analytics); + + expect(LogRetentionLogic.actions.saveLogRetention).toHaveBeenCalledWith( + ELogRetentionOptions.Analytics, + true + ); + }); + + it('will do nothing if logRetention option is not yet set', () => { + mount({ + logRetention: {}, + }); + jest.spyOn(LogRetentionLogic.actions, 'saveLogRetention'); + jest.spyOn(LogRetentionLogic.actions, 'setOpenedModal'); + + LogRetentionLogic.actions.toggleLogRetention(ELogRetentionOptions.API); + + expect(LogRetentionLogic.actions.saveLogRetention).not.toHaveBeenCalled(); + expect(LogRetentionLogic.actions.setOpenedModal).not.toHaveBeenCalled(); + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts new file mode 100644 index 0000000000000..28830f2edb1d9 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.ts @@ -0,0 +1,117 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { kea, MakeLogicType } from 'kea'; + +import { ELogRetentionOptions, ILogRetention, ILogRetentionServer } from './types'; +import { HttpLogic } from '../../../../shared/http'; +import { flashAPIErrors } from '../../../../shared/flash_messages'; +import { convertLogRetentionFromServerToClient } from './utils/convert_log_retention'; + +interface ILogRetentionActions { + clearLogRetentionUpdating(): { value: boolean }; + closeModals(): { value: boolean }; + fetchLogRetention(): { value: boolean }; + saveLogRetention( + option: ELogRetentionOptions, + enabled: boolean + ): { option: ELogRetentionOptions; enabled: boolean }; + setOpenedModal(option: ELogRetentionOptions): { option: ELogRetentionOptions }; + toggleLogRetention(option: ELogRetentionOptions): { option: ELogRetentionOptions }; + updateLogRetention(logRetention: ILogRetention): { logRetention: ILogRetention }; +} + +interface ILogRetentionValues { + logRetention: ILogRetention | null; + isLogRetentionUpdating: boolean; + openedModal: ELogRetentionOptions | null; +} + +export const LogRetentionLogic = kea>({ + path: ['enterprise_search', 'app_search', 'log_retention_logic'], + actions: () => ({ + clearLogRetentionUpdating: true, + closeModals: true, + fetchLogRetention: true, + saveLogRetention: (option, enabled) => ({ enabled, option }), + setOpenedModal: (option) => ({ option }), + toggleLogRetention: (option) => ({ option }), + updateLogRetention: (logRetention) => ({ logRetention }), + }), + reducers: () => ({ + logRetention: [ + null, + { + updateLogRetention: (_, { logRetention }) => logRetention, + }, + ], + isLogRetentionUpdating: [ + false, + { + clearLogRetentionUpdating: () => false, + closeModals: () => false, + fetchLogRetention: () => true, + toggleLogRetention: () => true, + }, + ], + openedModal: [ + null, + { + closeModals: () => null, + saveLogRetention: () => null, + setOpenedModal: (_, { option }) => option, + }, + ], + }), + listeners: ({ actions, values }) => ({ + fetchLogRetention: async () => { + try { + const { http } = HttpLogic.values; + const response = await http.get('/api/app_search/log_settings'); + actions.updateLogRetention( + convertLogRetentionFromServerToClient(response as ILogRetentionServer) + ); + } catch (e) { + flashAPIErrors(e); + } finally { + actions.clearLogRetentionUpdating(); + } + }, + saveLogRetention: async ({ enabled, option }) => { + const updateData = { [option]: { enabled } }; + + try { + const { http } = HttpLogic.values; + const response = await http.put('/api/app_search/log_settings', { + body: JSON.stringify(updateData), + }); + actions.updateLogRetention( + convertLogRetentionFromServerToClient(response as ILogRetentionServer) + ); + } catch (e) { + flashAPIErrors(e); + } finally { + actions.clearLogRetentionUpdating(); + } + }, + toggleLogRetention: ({ option }) => { + const logRetention = values.logRetention?.[option]; + + // If the user has found a way to call this before we've retrieved + // log retention settings from the server, short circuit this and return early + if (!logRetention) { + return; + } + + const optionIsAlreadyEnabled = logRetention.enabled; + if (optionIsAlreadyEnabled) { + actions.setOpenedModal(option); + } else { + actions.saveLogRetention(option, true); + } + }, + }), +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/types.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/types.ts new file mode 100644 index 0000000000000..7d4f30f88f38f --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/types.ts @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export enum ELogRetentionOptions { + Analytics = 'analytics', + API = 'api', +} + +export interface ILogRetention { + [ELogRetentionOptions.Analytics]: ILogRetentionSettings; + [ELogRetentionOptions.API]: ILogRetentionSettings; +} + +export interface ILogRetentionPolicy { + isDefault: boolean; + minAgeDays: number | null; +} + +export interface ILogRetentionSettings { + disabledAt?: string | null; + enabled?: boolean; + retentionPolicy?: ILogRetentionPolicy | null; +} + +export interface ILogRetentionServer { + [ELogRetentionOptions.Analytics]: ILogRetentionServerSettings; + [ELogRetentionOptions.API]: ILogRetentionServerSettings; +} + +export interface ILogRetentionServerPolicy { + is_default: boolean; + min_age_days: number | null; +} + +export interface ILogRetentionServerSettings { + disabled_at: string | null; + enabled: boolean; + retention_policy: ILogRetentionServerPolicy | null; +} diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/utils/convert_log_retention.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/utils/convert_log_retention.test.ts new file mode 100644 index 0000000000000..b49b2afe50831 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/utils/convert_log_retention.test.ts @@ -0,0 +1,64 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { convertLogRetentionFromServerToClient } from './convert_log_retention'; + +describe('convertLogRetentionFromServerToClient', () => { + it('converts log retention from server to client', () => { + expect( + convertLogRetentionFromServerToClient({ + analytics: { + disabled_at: null, + enabled: true, + retention_policy: { is_default: true, min_age_days: 180 }, + }, + api: { + disabled_at: null, + enabled: true, + retention_policy: { is_default: true, min_age_days: 180 }, + }, + }) + ).toEqual({ + analytics: { + disabledAt: null, + enabled: true, + retentionPolicy: { isDefault: true, minAgeDays: 180 }, + }, + api: { + disabledAt: null, + enabled: true, + retentionPolicy: { isDefault: true, minAgeDays: 180 }, + }, + }); + }); + + it('handles null retention policies and null min_age_days', () => { + expect( + convertLogRetentionFromServerToClient({ + analytics: { + disabled_at: null, + enabled: true, + retention_policy: null, + }, + api: { + disabled_at: null, + enabled: true, + retention_policy: { is_default: true, min_age_days: null }, + }, + }) + ).toEqual({ + analytics: { + disabledAt: null, + enabled: true, + retentionPolicy: null, + }, + api: { + disabledAt: null, + enabled: true, + retentionPolicy: { isDefault: true, minAgeDays: null }, + }, + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/utils/convert_log_retention.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/utils/convert_log_retention.ts new file mode 100644 index 0000000000000..1c0818fc286f2 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/utils/convert_log_retention.ts @@ -0,0 +1,45 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { + ELogRetentionOptions, + ILogRetention, + ILogRetentionPolicy, + ILogRetentionServer, + ILogRetentionServerPolicy, + ILogRetentionServerSettings, + ILogRetentionSettings, +} from '../types'; + +export const convertLogRetentionFromServerToClient = ( + logRetention: ILogRetentionServer +): ILogRetention => ({ + [ELogRetentionOptions.Analytics]: convertLogRetentionSettingsFromServerToClient( + logRetention[ELogRetentionOptions.Analytics] + ), + [ELogRetentionOptions.API]: convertLogRetentionSettingsFromServerToClient( + logRetention[ELogRetentionOptions.API] + ), +}); + +const convertLogRetentionSettingsFromServerToClient = ({ + disabled_at: disabledAt, + enabled, + retention_policy: retentionPolicy, +}: ILogRetentionServerSettings): ILogRetentionSettings => ({ + disabledAt, + enabled, + retentionPolicy: + retentionPolicy === null ? null : convertLogRetentionPolicyFromServerToClient(retentionPolicy), +}); + +const convertLogRetentionPolicyFromServerToClient = ({ + min_age_days: minAgeDays, + is_default: isDefault, +}: ILogRetentionServerPolicy): ILogRetentionPolicy => ({ + isDefault, + minAgeDays, +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/settings.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/settings.tsx index e5e86f3e39734..13079bb380f13 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/settings.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/settings.tsx @@ -6,30 +6,21 @@ import React from 'react'; -import { i18n } from '@kbn/i18n'; import { EuiPageHeader, EuiPageHeaderSection, EuiPageContentBody, EuiTitle } from '@elastic/eui'; import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; import { FlashMessages } from '../../../shared/flash_messages'; +import { SETTINGS_TITLE } from './'; + export const Settings: React.FC = () => { return ( <> - + -

- {i18n.translate('xpack.enterpriseSearch.appSearch.settings.title', { - defaultMessage: 'Settings', - })} -

+

{SETTINGS_TITLE}

diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/index.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/index.test.tsx index 700b903efe59b..11387734e9f9e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/index.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/index.test.tsx @@ -16,7 +16,7 @@ import { shallow } from 'enzyme'; import { Layout, SideNav, SideNavLink } from '../shared/layout'; import { SetupGuide } from './components/setup_guide'; import { ErrorConnecting } from './components/error_connecting'; -import { EngineOverview } from './components/engine_overview'; +import { EnginesOverview } from './components/engines'; import { EngineRouter } from './components/engine'; import { AppSearch, AppSearchUnconfigured, AppSearchConfigured, AppSearchNav } from './'; @@ -57,7 +57,7 @@ describe('AppSearchConfigured', () => { expect(wrapper.find(Layout)).toHaveLength(2); expect(wrapper.find(Layout).last().prop('readOnlyMode')).toBeFalsy(); - expect(wrapper.find(EngineOverview)).toHaveLength(1); + expect(wrapper.find(EnginesOverview)).toHaveLength(1); expect(wrapper.find(EngineRouter)).toHaveLength(1); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/index.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/index.tsx index f32b0b256b898..4571ef10286e4 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/index.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/index.tsx @@ -8,8 +8,6 @@ import React, { useEffect } from 'react'; import { Route, Redirect, Switch } from 'react-router-dom'; import { useActions, useValues } from 'kea'; -import { i18n } from '@kbn/i18n'; - import { getAppSearchUrl } from '../shared/enterprise_search_url'; import { KibanaLogic } from '../shared/kibana'; import { HttpLogic } from '../shared/http'; @@ -33,9 +31,10 @@ import { import { SetupGuide } from './components/setup_guide'; import { ErrorConnecting } from './components/error_connecting'; import { NotFound } from '../shared/not_found'; -import { EngineOverview } from './components/engine_overview'; -import { Settings } from './components/settings'; -import { Credentials } from './components/credentials'; +import { EnginesOverview, ENGINES_TITLE } from './components/engines'; +import { Settings, SETTINGS_TITLE } from './components/settings'; +import { Credentials, CREDENTIALS_TITLE } from './components/credentials'; +import { ROLE_MAPPINGS_TITLE } from './components/role_mappings'; export const AppSearch: React.FC = (props) => { const { config } = useValues(KibanaLogic); @@ -82,7 +81,7 @@ export const AppSearchConfigured: React.FC = (props) => { - + @@ -113,29 +112,15 @@ export const AppSearchNav: React.FC = ({ subNav }) => { return ( - {i18n.translate('xpack.enterpriseSearch.appSearch.nav.engines', { - defaultMessage: 'Engines', - })} + {ENGINES_TITLE} - {canViewSettings && ( - - {i18n.translate('xpack.enterpriseSearch.appSearch.nav.settings', { - defaultMessage: 'Settings', - })} - - )} + {canViewSettings && {SETTINGS_TITLE}} {canViewAccountCredentials && ( - - {i18n.translate('xpack.enterpriseSearch.appSearch.nav.credentials', { - defaultMessage: 'Credentials', - })} - + {CREDENTIALS_TITLE} )} {canViewRoleMappings && ( - {i18n.translate('xpack.enterpriseSearch.appSearch.nav.roleMappings', { - defaultMessage: 'Role Mappings', - })} + {ROLE_MAPPINGS_TITLE} )} diff --git a/x-pack/plugins/ingest_manager/CHANGELOG.md b/x-pack/plugins/fleet/CHANGELOG.md similarity index 100% rename from x-pack/plugins/ingest_manager/CHANGELOG.md rename to x-pack/plugins/fleet/CHANGELOG.md diff --git a/x-pack/plugins/ingest_manager/README.md b/x-pack/plugins/fleet/README.md similarity index 97% rename from x-pack/plugins/ingest_manager/README.md rename to x-pack/plugins/fleet/README.md index ade5985782c89..78ac2e3bdfdbe 100644 --- a/x-pack/plugins/ingest_manager/README.md +++ b/x-pack/plugins/fleet/README.md @@ -2,7 +2,7 @@ ## Plugin -- The plugin is enabled by default. See the TypeScript type for the [the available plugin configuration options](https://github.com/elastic/kibana/blob/master/x-pack/plugins/ingest_manager/common/types/index.ts#L9-L27) +- The plugin is enabled by default. See the TypeScript type for the [the available plugin configuration options](https://github.com/elastic/kibana/blob/master/x-pack/plugins/fleet/common/types/index.ts#L9-L27) - Adding `xpack.fleet.enabled=false` will disable the plugin including the EPM and Fleet features. It will also remove the `PACKAGE_POLICY_API_ROUTES` and `AGENT_POLICY_API_ROUTES` values in [`common/constants/routes.ts`](./common/constants/routes.ts) - Adding `--xpack.fleet.agents.enabled=false` will disable the Fleet API & UI - [code for adding the routes](https://github.com/elastic/kibana/blob/1f27d349533b1c2865c10c45b2cf705d7416fb36/x-pack/plugins/ingest_manager/server/plugin.ts#L115-L133) diff --git a/x-pack/plugins/ingest_manager/common/constants/agent.ts b/x-pack/plugins/fleet/common/constants/agent.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/constants/agent.ts rename to x-pack/plugins/fleet/common/constants/agent.ts diff --git a/x-pack/plugins/ingest_manager/common/constants/agent_policy.ts b/x-pack/plugins/fleet/common/constants/agent_policy.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/constants/agent_policy.ts rename to x-pack/plugins/fleet/common/constants/agent_policy.ts diff --git a/x-pack/plugins/ingest_manager/common/constants/enrollment_api_key.ts b/x-pack/plugins/fleet/common/constants/enrollment_api_key.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/constants/enrollment_api_key.ts rename to x-pack/plugins/fleet/common/constants/enrollment_api_key.ts diff --git a/x-pack/plugins/ingest_manager/common/constants/epm.ts b/x-pack/plugins/fleet/common/constants/epm.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/constants/epm.ts rename to x-pack/plugins/fleet/common/constants/epm.ts diff --git a/x-pack/plugins/ingest_manager/common/constants/index.ts b/x-pack/plugins/fleet/common/constants/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/constants/index.ts rename to x-pack/plugins/fleet/common/constants/index.ts diff --git a/x-pack/plugins/ingest_manager/common/constants/output.ts b/x-pack/plugins/fleet/common/constants/output.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/constants/output.ts rename to x-pack/plugins/fleet/common/constants/output.ts diff --git a/x-pack/plugins/ingest_manager/common/constants/package_policy.ts b/x-pack/plugins/fleet/common/constants/package_policy.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/constants/package_policy.ts rename to x-pack/plugins/fleet/common/constants/package_policy.ts diff --git a/x-pack/plugins/ingest_manager/common/constants/plugin.ts b/x-pack/plugins/fleet/common/constants/plugin.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/constants/plugin.ts rename to x-pack/plugins/fleet/common/constants/plugin.ts diff --git a/x-pack/plugins/ingest_manager/common/constants/routes.ts b/x-pack/plugins/fleet/common/constants/routes.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/constants/routes.ts rename to x-pack/plugins/fleet/common/constants/routes.ts diff --git a/x-pack/plugins/ingest_manager/common/constants/settings.ts b/x-pack/plugins/fleet/common/constants/settings.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/constants/settings.ts rename to x-pack/plugins/fleet/common/constants/settings.ts diff --git a/x-pack/plugins/ingest_manager/common/index.ts b/x-pack/plugins/fleet/common/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/index.ts rename to x-pack/plugins/fleet/common/index.ts diff --git a/x-pack/plugins/ingest_manager/common/mocks.ts b/x-pack/plugins/fleet/common/mocks.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/mocks.ts rename to x-pack/plugins/fleet/common/mocks.ts diff --git a/x-pack/plugins/ingest_manager/common/openapi/README.md b/x-pack/plugins/fleet/common/openapi/README.md similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/README.md rename to x-pack/plugins/fleet/common/openapi/README.md diff --git a/x-pack/plugins/ingest_manager/common/openapi/bundled.json b/x-pack/plugins/fleet/common/openapi/bundled.json similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/bundled.json rename to x-pack/plugins/fleet/common/openapi/bundled.json diff --git a/x-pack/plugins/ingest_manager/common/openapi/bundled.yaml b/x-pack/plugins/fleet/common/openapi/bundled.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/bundled.yaml rename to x-pack/plugins/fleet/common/openapi/bundled.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/components/README.md b/x-pack/plugins/fleet/common/openapi/components/README.md similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/components/README.md rename to x-pack/plugins/fleet/common/openapi/components/README.md diff --git a/x-pack/plugins/ingest_manager/common/openapi/components/headers/kbn_xsrf.yaml b/x-pack/plugins/fleet/common/openapi/components/headers/kbn_xsrf.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/components/headers/kbn_xsrf.yaml rename to x-pack/plugins/fleet/common/openapi/components/headers/kbn_xsrf.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/components/parameters/kuery.yaml b/x-pack/plugins/fleet/common/openapi/components/parameters/kuery.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/components/parameters/kuery.yaml rename to x-pack/plugins/fleet/common/openapi/components/parameters/kuery.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/components/parameters/page_index.yaml b/x-pack/plugins/fleet/common/openapi/components/parameters/page_index.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/components/parameters/page_index.yaml rename to x-pack/plugins/fleet/common/openapi/components/parameters/page_index.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/components/parameters/page_size.yaml b/x-pack/plugins/fleet/common/openapi/components/parameters/page_size.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/components/parameters/page_size.yaml rename to x-pack/plugins/fleet/common/openapi/components/parameters/page_size.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/components/schemas/access_api_key.yaml b/x-pack/plugins/fleet/common/openapi/components/schemas/access_api_key.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/components/schemas/access_api_key.yaml rename to x-pack/plugins/fleet/common/openapi/components/schemas/access_api_key.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/components/schemas/agent.yaml b/x-pack/plugins/fleet/common/openapi/components/schemas/agent.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/components/schemas/agent.yaml rename to x-pack/plugins/fleet/common/openapi/components/schemas/agent.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/components/schemas/agent_event.yaml b/x-pack/plugins/fleet/common/openapi/components/schemas/agent_event.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/components/schemas/agent_event.yaml rename to x-pack/plugins/fleet/common/openapi/components/schemas/agent_event.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/components/schemas/agent_metadata.yaml b/x-pack/plugins/fleet/common/openapi/components/schemas/agent_metadata.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/components/schemas/agent_metadata.yaml rename to x-pack/plugins/fleet/common/openapi/components/schemas/agent_metadata.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/components/schemas/agent_policy.yaml b/x-pack/plugins/fleet/common/openapi/components/schemas/agent_policy.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/components/schemas/agent_policy.yaml rename to x-pack/plugins/fleet/common/openapi/components/schemas/agent_policy.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/components/schemas/agent_status.yaml b/x-pack/plugins/fleet/common/openapi/components/schemas/agent_status.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/components/schemas/agent_status.yaml rename to x-pack/plugins/fleet/common/openapi/components/schemas/agent_status.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/components/schemas/agent_type.yaml b/x-pack/plugins/fleet/common/openapi/components/schemas/agent_type.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/components/schemas/agent_type.yaml rename to x-pack/plugins/fleet/common/openapi/components/schemas/agent_type.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/components/schemas/bulk_upgrade_agents.yaml b/x-pack/plugins/fleet/common/openapi/components/schemas/bulk_upgrade_agents.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/components/schemas/bulk_upgrade_agents.yaml rename to x-pack/plugins/fleet/common/openapi/components/schemas/bulk_upgrade_agents.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/components/schemas/enrollment_api_key.yaml b/x-pack/plugins/fleet/common/openapi/components/schemas/enrollment_api_key.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/components/schemas/enrollment_api_key.yaml rename to x-pack/plugins/fleet/common/openapi/components/schemas/enrollment_api_key.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/components/schemas/new_agent_event.yaml b/x-pack/plugins/fleet/common/openapi/components/schemas/new_agent_event.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/components/schemas/new_agent_event.yaml rename to x-pack/plugins/fleet/common/openapi/components/schemas/new_agent_event.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/components/schemas/new_agent_policy.yaml b/x-pack/plugins/fleet/common/openapi/components/schemas/new_agent_policy.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/components/schemas/new_agent_policy.yaml rename to x-pack/plugins/fleet/common/openapi/components/schemas/new_agent_policy.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/components/schemas/new_package_policy.yaml b/x-pack/plugins/fleet/common/openapi/components/schemas/new_package_policy.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/components/schemas/new_package_policy.yaml rename to x-pack/plugins/fleet/common/openapi/components/schemas/new_package_policy.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/components/schemas/package_info.yaml b/x-pack/plugins/fleet/common/openapi/components/schemas/package_info.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/components/schemas/package_info.yaml rename to x-pack/plugins/fleet/common/openapi/components/schemas/package_info.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/components/schemas/package_policy.yaml b/x-pack/plugins/fleet/common/openapi/components/schemas/package_policy.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/components/schemas/package_policy.yaml rename to x-pack/plugins/fleet/common/openapi/components/schemas/package_policy.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/components/schemas/search_result.yaml b/x-pack/plugins/fleet/common/openapi/components/schemas/search_result.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/components/schemas/search_result.yaml rename to x-pack/plugins/fleet/common/openapi/components/schemas/search_result.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/components/schemas/upgrade_agent.yaml b/x-pack/plugins/fleet/common/openapi/components/schemas/upgrade_agent.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/components/schemas/upgrade_agent.yaml rename to x-pack/plugins/fleet/common/openapi/components/schemas/upgrade_agent.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/entrypoint.yaml b/x-pack/plugins/fleet/common/openapi/entrypoint.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/entrypoint.yaml rename to x-pack/plugins/fleet/common/openapi/entrypoint.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/paths/README.md b/x-pack/plugins/fleet/common/openapi/paths/README.md similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/paths/README.md rename to x-pack/plugins/fleet/common/openapi/paths/README.md diff --git a/x-pack/plugins/ingest_manager/common/openapi/paths/agent_policies.yaml b/x-pack/plugins/fleet/common/openapi/paths/agent_policies.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/paths/agent_policies.yaml rename to x-pack/plugins/fleet/common/openapi/paths/agent_policies.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/paths/agent_policies@delete.yaml b/x-pack/plugins/fleet/common/openapi/paths/agent_policies@delete.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/paths/agent_policies@delete.yaml rename to x-pack/plugins/fleet/common/openapi/paths/agent_policies@delete.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/paths/agent_policies@{agent_policy_id}.yaml b/x-pack/plugins/fleet/common/openapi/paths/agent_policies@{agent_policy_id}.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/paths/agent_policies@{agent_policy_id}.yaml rename to x-pack/plugins/fleet/common/openapi/paths/agent_policies@{agent_policy_id}.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/paths/agent_policies@{agent_policy_id}@copy.yaml b/x-pack/plugins/fleet/common/openapi/paths/agent_policies@{agent_policy_id}@copy.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/paths/agent_policies@{agent_policy_id}@copy.yaml rename to x-pack/plugins/fleet/common/openapi/paths/agent_policies@{agent_policy_id}@copy.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/paths/agent_status.yaml b/x-pack/plugins/fleet/common/openapi/paths/agent_status.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/paths/agent_status.yaml rename to x-pack/plugins/fleet/common/openapi/paths/agent_status.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/paths/agents.yaml b/x-pack/plugins/fleet/common/openapi/paths/agents.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/paths/agents.yaml rename to x-pack/plugins/fleet/common/openapi/paths/agents.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/paths/agents@bulk_upgrade.yaml b/x-pack/plugins/fleet/common/openapi/paths/agents@bulk_upgrade.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/paths/agents@bulk_upgrade.yaml rename to x-pack/plugins/fleet/common/openapi/paths/agents@bulk_upgrade.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/paths/agents@enroll.yaml b/x-pack/plugins/fleet/common/openapi/paths/agents@enroll.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/paths/agents@enroll.yaml rename to x-pack/plugins/fleet/common/openapi/paths/agents@enroll.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/paths/agents@setup.yaml b/x-pack/plugins/fleet/common/openapi/paths/agents@setup.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/paths/agents@setup.yaml rename to x-pack/plugins/fleet/common/openapi/paths/agents@setup.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/paths/agents@{agent_id}.yaml b/x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/paths/agents@{agent_id}.yaml rename to x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/paths/agents@{agent_id}@acks.yaml b/x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}@acks.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/paths/agents@{agent_id}@acks.yaml rename to x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}@acks.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/paths/agents@{agent_id}@checkin.yaml b/x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}@checkin.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/paths/agents@{agent_id}@checkin.yaml rename to x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}@checkin.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/paths/agents@{agent_id}@events.yaml b/x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}@events.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/paths/agents@{agent_id}@events.yaml rename to x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}@events.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/paths/agents@{agent_id}@unenroll.yaml b/x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}@unenroll.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/paths/agents@{agent_id}@unenroll.yaml rename to x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}@unenroll.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/paths/agents@{agent_id}@upgrade.yaml b/x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}@upgrade.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/paths/agents@{agent_id}@upgrade.yaml rename to x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}@upgrade.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/paths/enrollment_api_keys.yaml b/x-pack/plugins/fleet/common/openapi/paths/enrollment_api_keys.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/paths/enrollment_api_keys.yaml rename to x-pack/plugins/fleet/common/openapi/paths/enrollment_api_keys.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/paths/enrollment_api_keys@{key_id}.yaml b/x-pack/plugins/fleet/common/openapi/paths/enrollment_api_keys@{key_id}.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/paths/enrollment_api_keys@{key_id}.yaml rename to x-pack/plugins/fleet/common/openapi/paths/enrollment_api_keys@{key_id}.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/paths/epm@categories.yaml b/x-pack/plugins/fleet/common/openapi/paths/epm@categories.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/paths/epm@categories.yaml rename to x-pack/plugins/fleet/common/openapi/paths/epm@categories.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/paths/epm@packages.yaml b/x-pack/plugins/fleet/common/openapi/paths/epm@packages.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/paths/epm@packages.yaml rename to x-pack/plugins/fleet/common/openapi/paths/epm@packages.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/paths/epm@packages@{pkgkey}.yaml b/x-pack/plugins/fleet/common/openapi/paths/epm@packages@{pkgkey}.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/paths/epm@packages@{pkgkey}.yaml rename to x-pack/plugins/fleet/common/openapi/paths/epm@packages@{pkgkey}.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/paths/install@{os_type}.yaml b/x-pack/plugins/fleet/common/openapi/paths/install@{os_type}.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/paths/install@{os_type}.yaml rename to x-pack/plugins/fleet/common/openapi/paths/install@{os_type}.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/paths/package_policies.yaml b/x-pack/plugins/fleet/common/openapi/paths/package_policies.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/paths/package_policies.yaml rename to x-pack/plugins/fleet/common/openapi/paths/package_policies.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/paths/package_policies@{package_policy_id}.yaml b/x-pack/plugins/fleet/common/openapi/paths/package_policies@{package_policy_id}.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/paths/package_policies@{package_policy_id}.yaml rename to x-pack/plugins/fleet/common/openapi/paths/package_policies@{package_policy_id}.yaml diff --git a/x-pack/plugins/ingest_manager/common/openapi/paths/setup.yaml b/x-pack/plugins/fleet/common/openapi/paths/setup.yaml similarity index 100% rename from x-pack/plugins/ingest_manager/common/openapi/paths/setup.yaml rename to x-pack/plugins/fleet/common/openapi/paths/setup.yaml diff --git a/x-pack/plugins/ingest_manager/common/services/agent_status.ts b/x-pack/plugins/fleet/common/services/agent_status.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/services/agent_status.ts rename to x-pack/plugins/fleet/common/services/agent_status.ts diff --git a/x-pack/plugins/ingest_manager/common/services/decode_cloud_id.test.ts b/x-pack/plugins/fleet/common/services/decode_cloud_id.test.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/services/decode_cloud_id.test.ts rename to x-pack/plugins/fleet/common/services/decode_cloud_id.test.ts diff --git a/x-pack/plugins/ingest_manager/common/services/decode_cloud_id.ts b/x-pack/plugins/fleet/common/services/decode_cloud_id.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/services/decode_cloud_id.ts rename to x-pack/plugins/fleet/common/services/decode_cloud_id.ts diff --git a/x-pack/plugins/ingest_manager/common/services/full_agent_policy_kibana_config.test.ts b/x-pack/plugins/fleet/common/services/full_agent_policy_kibana_config.test.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/services/full_agent_policy_kibana_config.test.ts rename to x-pack/plugins/fleet/common/services/full_agent_policy_kibana_config.test.ts diff --git a/x-pack/plugins/ingest_manager/common/services/full_agent_policy_kibana_config.ts b/x-pack/plugins/fleet/common/services/full_agent_policy_kibana_config.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/services/full_agent_policy_kibana_config.ts rename to x-pack/plugins/fleet/common/services/full_agent_policy_kibana_config.ts diff --git a/x-pack/plugins/ingest_manager/common/services/full_agent_policy_to_yaml.ts b/x-pack/plugins/fleet/common/services/full_agent_policy_to_yaml.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/services/full_agent_policy_to_yaml.ts rename to x-pack/plugins/fleet/common/services/full_agent_policy_to_yaml.ts diff --git a/x-pack/plugins/ingest_manager/common/services/index.ts b/x-pack/plugins/fleet/common/services/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/services/index.ts rename to x-pack/plugins/fleet/common/services/index.ts diff --git a/x-pack/plugins/ingest_manager/common/services/is_agent_upgradeable.test.ts b/x-pack/plugins/fleet/common/services/is_agent_upgradeable.test.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/services/is_agent_upgradeable.test.ts rename to x-pack/plugins/fleet/common/services/is_agent_upgradeable.test.ts diff --git a/x-pack/plugins/ingest_manager/common/services/is_agent_upgradeable.ts b/x-pack/plugins/fleet/common/services/is_agent_upgradeable.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/services/is_agent_upgradeable.ts rename to x-pack/plugins/fleet/common/services/is_agent_upgradeable.ts diff --git a/x-pack/plugins/ingest_manager/common/services/is_diff_path_protocol.test.ts b/x-pack/plugins/fleet/common/services/is_diff_path_protocol.test.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/services/is_diff_path_protocol.test.ts rename to x-pack/plugins/fleet/common/services/is_diff_path_protocol.test.ts diff --git a/x-pack/plugins/ingest_manager/common/services/is_diff_path_protocol.ts b/x-pack/plugins/fleet/common/services/is_diff_path_protocol.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/services/is_diff_path_protocol.ts rename to x-pack/plugins/fleet/common/services/is_diff_path_protocol.ts diff --git a/x-pack/plugins/ingest_manager/common/services/is_valid_namespace.test.ts b/x-pack/plugins/fleet/common/services/is_valid_namespace.test.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/services/is_valid_namespace.test.ts rename to x-pack/plugins/fleet/common/services/is_valid_namespace.test.ts diff --git a/x-pack/plugins/ingest_manager/common/services/is_valid_namespace.ts b/x-pack/plugins/fleet/common/services/is_valid_namespace.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/services/is_valid_namespace.ts rename to x-pack/plugins/fleet/common/services/is_valid_namespace.ts diff --git a/x-pack/plugins/ingest_manager/common/services/license.ts b/x-pack/plugins/fleet/common/services/license.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/services/license.ts rename to x-pack/plugins/fleet/common/services/license.ts diff --git a/x-pack/plugins/ingest_manager/common/services/limited_package.ts b/x-pack/plugins/fleet/common/services/limited_package.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/services/limited_package.ts rename to x-pack/plugins/fleet/common/services/limited_package.ts diff --git a/x-pack/plugins/ingest_manager/common/services/package_policies_to_agent_inputs.test.ts b/x-pack/plugins/fleet/common/services/package_policies_to_agent_inputs.test.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/services/package_policies_to_agent_inputs.test.ts rename to x-pack/plugins/fleet/common/services/package_policies_to_agent_inputs.test.ts diff --git a/x-pack/plugins/ingest_manager/common/services/package_policies_to_agent_inputs.ts b/x-pack/plugins/fleet/common/services/package_policies_to_agent_inputs.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/services/package_policies_to_agent_inputs.ts rename to x-pack/plugins/fleet/common/services/package_policies_to_agent_inputs.ts diff --git a/x-pack/plugins/ingest_manager/common/services/package_to_package_policy.test.ts b/x-pack/plugins/fleet/common/services/package_to_package_policy.test.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/services/package_to_package_policy.test.ts rename to x-pack/plugins/fleet/common/services/package_to_package_policy.test.ts diff --git a/x-pack/plugins/ingest_manager/common/services/package_to_package_policy.ts b/x-pack/plugins/fleet/common/services/package_to_package_policy.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/services/package_to_package_policy.ts rename to x-pack/plugins/fleet/common/services/package_to_package_policy.ts diff --git a/x-pack/plugins/ingest_manager/common/services/routes.ts b/x-pack/plugins/fleet/common/services/routes.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/services/routes.ts rename to x-pack/plugins/fleet/common/services/routes.ts diff --git a/x-pack/plugins/ingest_manager/common/types/index.ts b/x-pack/plugins/fleet/common/types/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/types/index.ts rename to x-pack/plugins/fleet/common/types/index.ts diff --git a/x-pack/plugins/ingest_manager/common/types/models/agent.ts b/x-pack/plugins/fleet/common/types/models/agent.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/types/models/agent.ts rename to x-pack/plugins/fleet/common/types/models/agent.ts diff --git a/x-pack/plugins/ingest_manager/common/types/models/agent_policy.ts b/x-pack/plugins/fleet/common/types/models/agent_policy.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/types/models/agent_policy.ts rename to x-pack/plugins/fleet/common/types/models/agent_policy.ts diff --git a/x-pack/plugins/ingest_manager/common/types/models/data_stream.ts b/x-pack/plugins/fleet/common/types/models/data_stream.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/types/models/data_stream.ts rename to x-pack/plugins/fleet/common/types/models/data_stream.ts diff --git a/x-pack/plugins/ingest_manager/common/types/models/enrollment_api_key.ts b/x-pack/plugins/fleet/common/types/models/enrollment_api_key.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/types/models/enrollment_api_key.ts rename to x-pack/plugins/fleet/common/types/models/enrollment_api_key.ts diff --git a/x-pack/plugins/ingest_manager/common/types/models/epm.ts b/x-pack/plugins/fleet/common/types/models/epm.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/types/models/epm.ts rename to x-pack/plugins/fleet/common/types/models/epm.ts diff --git a/x-pack/plugins/ingest_manager/common/types/models/index.ts b/x-pack/plugins/fleet/common/types/models/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/types/models/index.ts rename to x-pack/plugins/fleet/common/types/models/index.ts diff --git a/x-pack/plugins/ingest_manager/common/types/models/output.ts b/x-pack/plugins/fleet/common/types/models/output.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/types/models/output.ts rename to x-pack/plugins/fleet/common/types/models/output.ts diff --git a/x-pack/plugins/ingest_manager/common/types/models/package_policy.ts b/x-pack/plugins/fleet/common/types/models/package_policy.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/types/models/package_policy.ts rename to x-pack/plugins/fleet/common/types/models/package_policy.ts diff --git a/x-pack/plugins/ingest_manager/common/types/models/settings.ts b/x-pack/plugins/fleet/common/types/models/settings.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/types/models/settings.ts rename to x-pack/plugins/fleet/common/types/models/settings.ts diff --git a/x-pack/plugins/ingest_manager/common/types/rest_spec/agent.ts b/x-pack/plugins/fleet/common/types/rest_spec/agent.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/types/rest_spec/agent.ts rename to x-pack/plugins/fleet/common/types/rest_spec/agent.ts diff --git a/x-pack/plugins/ingest_manager/common/types/rest_spec/agent_policy.ts b/x-pack/plugins/fleet/common/types/rest_spec/agent_policy.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/types/rest_spec/agent_policy.ts rename to x-pack/plugins/fleet/common/types/rest_spec/agent_policy.ts diff --git a/x-pack/plugins/ingest_manager/common/types/rest_spec/app.ts b/x-pack/plugins/fleet/common/types/rest_spec/app.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/types/rest_spec/app.ts rename to x-pack/plugins/fleet/common/types/rest_spec/app.ts diff --git a/x-pack/plugins/ingest_manager/common/types/rest_spec/common.ts b/x-pack/plugins/fleet/common/types/rest_spec/common.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/types/rest_spec/common.ts rename to x-pack/plugins/fleet/common/types/rest_spec/common.ts diff --git a/x-pack/plugins/ingest_manager/common/types/rest_spec/data_stream.ts b/x-pack/plugins/fleet/common/types/rest_spec/data_stream.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/types/rest_spec/data_stream.ts rename to x-pack/plugins/fleet/common/types/rest_spec/data_stream.ts diff --git a/x-pack/plugins/ingest_manager/common/types/rest_spec/enrollment_api_key.ts b/x-pack/plugins/fleet/common/types/rest_spec/enrollment_api_key.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/types/rest_spec/enrollment_api_key.ts rename to x-pack/plugins/fleet/common/types/rest_spec/enrollment_api_key.ts diff --git a/x-pack/plugins/ingest_manager/common/types/rest_spec/epm.ts b/x-pack/plugins/fleet/common/types/rest_spec/epm.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/types/rest_spec/epm.ts rename to x-pack/plugins/fleet/common/types/rest_spec/epm.ts diff --git a/x-pack/plugins/ingest_manager/common/types/rest_spec/fleet_setup.ts b/x-pack/plugins/fleet/common/types/rest_spec/fleet_setup.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/types/rest_spec/fleet_setup.ts rename to x-pack/plugins/fleet/common/types/rest_spec/fleet_setup.ts diff --git a/x-pack/plugins/ingest_manager/common/types/rest_spec/index.ts b/x-pack/plugins/fleet/common/types/rest_spec/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/types/rest_spec/index.ts rename to x-pack/plugins/fleet/common/types/rest_spec/index.ts diff --git a/x-pack/plugins/ingest_manager/common/types/rest_spec/ingest_setup.ts b/x-pack/plugins/fleet/common/types/rest_spec/ingest_setup.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/types/rest_spec/ingest_setup.ts rename to x-pack/plugins/fleet/common/types/rest_spec/ingest_setup.ts diff --git a/x-pack/plugins/ingest_manager/common/types/rest_spec/install_script.ts b/x-pack/plugins/fleet/common/types/rest_spec/install_script.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/types/rest_spec/install_script.ts rename to x-pack/plugins/fleet/common/types/rest_spec/install_script.ts diff --git a/x-pack/plugins/ingest_manager/common/types/rest_spec/output.ts b/x-pack/plugins/fleet/common/types/rest_spec/output.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/types/rest_spec/output.ts rename to x-pack/plugins/fleet/common/types/rest_spec/output.ts diff --git a/x-pack/plugins/ingest_manager/common/types/rest_spec/package_policy.ts b/x-pack/plugins/fleet/common/types/rest_spec/package_policy.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/types/rest_spec/package_policy.ts rename to x-pack/plugins/fleet/common/types/rest_spec/package_policy.ts diff --git a/x-pack/plugins/ingest_manager/common/types/rest_spec/settings.ts b/x-pack/plugins/fleet/common/types/rest_spec/settings.ts similarity index 100% rename from x-pack/plugins/ingest_manager/common/types/rest_spec/settings.ts rename to x-pack/plugins/fleet/common/types/rest_spec/settings.ts diff --git a/x-pack/plugins/ingest_manager/dev_docs/actions_and_events.md b/x-pack/plugins/fleet/dev_docs/actions_and_events.md similarity index 100% rename from x-pack/plugins/ingest_manager/dev_docs/actions_and_events.md rename to x-pack/plugins/fleet/dev_docs/actions_and_events.md diff --git a/x-pack/plugins/ingest_manager/dev_docs/api/agents_acks.md b/x-pack/plugins/fleet/dev_docs/api/agents_acks.md similarity index 100% rename from x-pack/plugins/ingest_manager/dev_docs/api/agents_acks.md rename to x-pack/plugins/fleet/dev_docs/api/agents_acks.md diff --git a/x-pack/plugins/ingest_manager/dev_docs/api/agents_checkin.md b/x-pack/plugins/fleet/dev_docs/api/agents_checkin.md similarity index 100% rename from x-pack/plugins/ingest_manager/dev_docs/api/agents_checkin.md rename to x-pack/plugins/fleet/dev_docs/api/agents_checkin.md diff --git a/x-pack/plugins/ingest_manager/dev_docs/api/agents_enroll.md b/x-pack/plugins/fleet/dev_docs/api/agents_enroll.md similarity index 100% rename from x-pack/plugins/ingest_manager/dev_docs/api/agents_enroll.md rename to x-pack/plugins/fleet/dev_docs/api/agents_enroll.md diff --git a/x-pack/plugins/ingest_manager/dev_docs/api/agents_list.md b/x-pack/plugins/fleet/dev_docs/api/agents_list.md similarity index 100% rename from x-pack/plugins/ingest_manager/dev_docs/api/agents_list.md rename to x-pack/plugins/fleet/dev_docs/api/agents_list.md diff --git a/x-pack/plugins/ingest_manager/dev_docs/api/agents_unenroll.md b/x-pack/plugins/fleet/dev_docs/api/agents_unenroll.md similarity index 100% rename from x-pack/plugins/ingest_manager/dev_docs/api/agents_unenroll.md rename to x-pack/plugins/fleet/dev_docs/api/agents_unenroll.md diff --git a/x-pack/plugins/ingest_manager/dev_docs/api/epm.md b/x-pack/plugins/fleet/dev_docs/api/epm.md similarity index 100% rename from x-pack/plugins/ingest_manager/dev_docs/api/epm.md rename to x-pack/plugins/fleet/dev_docs/api/epm.md diff --git a/x-pack/plugins/ingest_manager/dev_docs/api_integration_tests.md b/x-pack/plugins/fleet/dev_docs/api_integration_tests.md similarity index 100% rename from x-pack/plugins/ingest_manager/dev_docs/api_integration_tests.md rename to x-pack/plugins/fleet/dev_docs/api_integration_tests.md diff --git a/x-pack/plugins/ingest_manager/dev_docs/api_keys.md b/x-pack/plugins/fleet/dev_docs/api_keys.md similarity index 100% rename from x-pack/plugins/ingest_manager/dev_docs/api_keys.md rename to x-pack/plugins/fleet/dev_docs/api_keys.md diff --git a/x-pack/plugins/ingest_manager/dev_docs/definitions.md b/x-pack/plugins/fleet/dev_docs/definitions.md similarity index 100% rename from x-pack/plugins/ingest_manager/dev_docs/definitions.md rename to x-pack/plugins/fleet/dev_docs/definitions.md diff --git a/x-pack/plugins/ingest_manager/dev_docs/epm.md b/x-pack/plugins/fleet/dev_docs/epm.md similarity index 100% rename from x-pack/plugins/ingest_manager/dev_docs/epm.md rename to x-pack/plugins/fleet/dev_docs/epm.md diff --git a/x-pack/plugins/ingest_manager/dev_docs/fleet_agent_communication.md b/x-pack/plugins/fleet/dev_docs/fleet_agent_communication.md similarity index 100% rename from x-pack/plugins/ingest_manager/dev_docs/fleet_agent_communication.md rename to x-pack/plugins/fleet/dev_docs/fleet_agent_communication.md diff --git a/x-pack/plugins/ingest_manager/dev_docs/fleet_agents_interactions_detailed.md b/x-pack/plugins/fleet/dev_docs/fleet_agents_interactions_detailed.md similarity index 100% rename from x-pack/plugins/ingest_manager/dev_docs/fleet_agents_interactions_detailed.md rename to x-pack/plugins/fleet/dev_docs/fleet_agents_interactions_detailed.md diff --git a/x-pack/plugins/ingest_manager/dev_docs/indexing_strategy.md b/x-pack/plugins/fleet/dev_docs/indexing_strategy.md similarity index 100% rename from x-pack/plugins/ingest_manager/dev_docs/indexing_strategy.md rename to x-pack/plugins/fleet/dev_docs/indexing_strategy.md diff --git a/x-pack/plugins/ingest_manager/dev_docs/schema/agent_checkin.mml b/x-pack/plugins/fleet/dev_docs/schema/agent_checkin.mml similarity index 100% rename from x-pack/plugins/ingest_manager/dev_docs/schema/agent_checkin.mml rename to x-pack/plugins/fleet/dev_docs/schema/agent_checkin.mml diff --git a/x-pack/plugins/ingest_manager/dev_docs/schema/agent_checkin.png b/x-pack/plugins/fleet/dev_docs/schema/agent_checkin.png similarity index 100% rename from x-pack/plugins/ingest_manager/dev_docs/schema/agent_checkin.png rename to x-pack/plugins/fleet/dev_docs/schema/agent_checkin.png diff --git a/x-pack/plugins/ingest_manager/dev_docs/schema/agent_enroll.mml b/x-pack/plugins/fleet/dev_docs/schema/agent_enroll.mml similarity index 100% rename from x-pack/plugins/ingest_manager/dev_docs/schema/agent_enroll.mml rename to x-pack/plugins/fleet/dev_docs/schema/agent_enroll.mml diff --git a/x-pack/plugins/ingest_manager/dev_docs/schema/agent_enroll.png b/x-pack/plugins/fleet/dev_docs/schema/agent_enroll.png similarity index 100% rename from x-pack/plugins/ingest_manager/dev_docs/schema/agent_enroll.png rename to x-pack/plugins/fleet/dev_docs/schema/agent_enroll.png diff --git a/x-pack/plugins/ingest_manager/dev_docs/schema/saved_objects.mml b/x-pack/plugins/fleet/dev_docs/schema/saved_objects.mml similarity index 100% rename from x-pack/plugins/ingest_manager/dev_docs/schema/saved_objects.mml rename to x-pack/plugins/fleet/dev_docs/schema/saved_objects.mml diff --git a/x-pack/plugins/ingest_manager/dev_docs/schema/saved_objects.png b/x-pack/plugins/fleet/dev_docs/schema/saved_objects.png similarity index 100% rename from x-pack/plugins/ingest_manager/dev_docs/schema/saved_objects.png rename to x-pack/plugins/fleet/dev_docs/schema/saved_objects.png diff --git a/x-pack/plugins/ingest_manager/dev_docs/tracing.md b/x-pack/plugins/fleet/dev_docs/tracing.md similarity index 100% rename from x-pack/plugins/ingest_manager/dev_docs/tracing.md rename to x-pack/plugins/fleet/dev_docs/tracing.md diff --git a/x-pack/plugins/ingest_manager/kibana.json b/x-pack/plugins/fleet/kibana.json similarity index 100% rename from x-pack/plugins/ingest_manager/kibana.json rename to x-pack/plugins/fleet/kibana.json diff --git a/x-pack/plugins/ingest_manager/package.json b/x-pack/plugins/fleet/package.json similarity index 100% rename from x-pack/plugins/ingest_manager/package.json rename to x-pack/plugins/fleet/package.json diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/alpha_flyout.tsx b/x-pack/plugins/fleet/public/applications/fleet/components/alpha_flyout.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/alpha_flyout.tsx rename to x-pack/plugins/fleet/public/applications/fleet/components/alpha_flyout.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/alpha_messaging.tsx b/x-pack/plugins/fleet/public/applications/fleet/components/alpha_messaging.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/alpha_messaging.tsx rename to x-pack/plugins/fleet/public/applications/fleet/components/alpha_messaging.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/context_menu_actions.tsx b/x-pack/plugins/fleet/public/applications/fleet/components/context_menu_actions.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/context_menu_actions.tsx rename to x-pack/plugins/fleet/public/applications/fleet/components/context_menu_actions.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/enrollment_instructions/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/components/enrollment_instructions/index.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/enrollment_instructions/index.tsx rename to x-pack/plugins/fleet/public/applications/fleet/components/enrollment_instructions/index.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/enrollment_instructions/manual/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/components/enrollment_instructions/manual/index.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/enrollment_instructions/manual/index.tsx rename to x-pack/plugins/fleet/public/applications/fleet/components/enrollment_instructions/manual/index.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/error.tsx b/x-pack/plugins/fleet/public/applications/fleet/components/error.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/error.tsx rename to x-pack/plugins/fleet/public/applications/fleet/components/error.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/header.tsx b/x-pack/plugins/fleet/public/applications/fleet/components/header.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/header.tsx rename to x-pack/plugins/fleet/public/applications/fleet/components/header.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/home_integration/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/components/home_integration/index.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/home_integration/index.tsx rename to x-pack/plugins/fleet/public/applications/fleet/components/home_integration/index.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/home_integration/tutorial_directory_header_link.tsx b/x-pack/plugins/fleet/public/applications/fleet/components/home_integration/tutorial_directory_header_link.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/home_integration/tutorial_directory_header_link.tsx rename to x-pack/plugins/fleet/public/applications/fleet/components/home_integration/tutorial_directory_header_link.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/home_integration/tutorial_directory_notice.tsx b/x-pack/plugins/fleet/public/applications/fleet/components/home_integration/tutorial_directory_notice.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/home_integration/tutorial_directory_notice.tsx rename to x-pack/plugins/fleet/public/applications/fleet/components/home_integration/tutorial_directory_notice.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/home_integration/tutorial_module_notice.tsx b/x-pack/plugins/fleet/public/applications/fleet/components/home_integration/tutorial_module_notice.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/home_integration/tutorial_module_notice.tsx rename to x-pack/plugins/fleet/public/applications/fleet/components/home_integration/tutorial_module_notice.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/index.ts b/x-pack/plugins/fleet/public/applications/fleet/components/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/index.ts rename to x-pack/plugins/fleet/public/applications/fleet/components/index.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/loading.tsx b/x-pack/plugins/fleet/public/applications/fleet/components/loading.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/loading.tsx rename to x-pack/plugins/fleet/public/applications/fleet/components/loading.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/package_icon.tsx b/x-pack/plugins/fleet/public/applications/fleet/components/package_icon.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/package_icon.tsx rename to x-pack/plugins/fleet/public/applications/fleet/components/package_icon.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/search_bar.tsx b/x-pack/plugins/fleet/public/applications/fleet/components/search_bar.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/search_bar.tsx rename to x-pack/plugins/fleet/public/applications/fleet/components/search_bar.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/settings_flyout.tsx b/x-pack/plugins/fleet/public/applications/fleet/components/settings_flyout.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/settings_flyout.tsx rename to x-pack/plugins/fleet/public/applications/fleet/components/settings_flyout.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/constants/index.ts b/x-pack/plugins/fleet/public/applications/fleet/constants/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/constants/index.ts rename to x-pack/plugins/fleet/public/applications/fleet/constants/index.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/constants/page_paths.ts b/x-pack/plugins/fleet/public/applications/fleet/constants/page_paths.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/constants/page_paths.ts rename to x-pack/plugins/fleet/public/applications/fleet/constants/page_paths.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/index.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/index.ts rename to x-pack/plugins/fleet/public/applications/fleet/hooks/index.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_breadcrumbs.tsx b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_breadcrumbs.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_breadcrumbs.tsx rename to x-pack/plugins/fleet/public/applications/fleet/hooks/use_breadcrumbs.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_capabilities.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_capabilities.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_capabilities.ts rename to x-pack/plugins/fleet/public/applications/fleet/hooks/use_capabilities.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_config.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_config.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_config.ts rename to x-pack/plugins/fleet/public/applications/fleet/hooks/use_config.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_core.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_core.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_core.ts rename to x-pack/plugins/fleet/public/applications/fleet/hooks/use_core.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_debounce.tsx b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_debounce.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_debounce.tsx rename to x-pack/plugins/fleet/public/applications/fleet/hooks/use_debounce.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_deps.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_deps.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_deps.ts rename to x-pack/plugins/fleet/public/applications/fleet/hooks/use_deps.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_fleet_status.tsx b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_fleet_status.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_fleet_status.tsx rename to x-pack/plugins/fleet/public/applications/fleet/hooks/use_fleet_status.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_input.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_input.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_input.ts rename to x-pack/plugins/fleet/public/applications/fleet/hooks/use_input.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_intra_app_state.tsx b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_intra_app_state.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_intra_app_state.tsx rename to x-pack/plugins/fleet/public/applications/fleet/hooks/use_intra_app_state.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_kibana_link.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_kibana_link.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_kibana_link.ts rename to x-pack/plugins/fleet/public/applications/fleet/hooks/use_kibana_link.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_kibana_version.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_kibana_version.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_kibana_version.ts rename to x-pack/plugins/fleet/public/applications/fleet/hooks/use_kibana_version.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_license.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_license.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_license.ts rename to x-pack/plugins/fleet/public/applications/fleet/hooks/use_license.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_link.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_link.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_link.ts rename to x-pack/plugins/fleet/public/applications/fleet/hooks/use_link.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_package_icon_type.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_package_icon_type.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_package_icon_type.ts rename to x-pack/plugins/fleet/public/applications/fleet/hooks/use_package_icon_type.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_pagination.tsx b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_pagination.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_pagination.tsx rename to x-pack/plugins/fleet/public/applications/fleet/hooks/use_pagination.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/agent_policy.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/agent_policy.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/agent_policy.ts rename to x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/agent_policy.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/agents.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/agents.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/agents.ts rename to x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/agents.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/app.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/app.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/app.ts rename to x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/app.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/data_stream.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/data_stream.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/data_stream.ts rename to x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/data_stream.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/enrollment_api_keys.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/enrollment_api_keys.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/enrollment_api_keys.ts rename to x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/enrollment_api_keys.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/epm.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/epm.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/epm.ts rename to x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/epm.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/index.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/index.ts rename to x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/index.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/outputs.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/outputs.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/outputs.ts rename to x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/outputs.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/package_policy.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/package_policy.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/package_policy.ts rename to x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/package_policy.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/settings.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/settings.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/settings.ts rename to x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/settings.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/setup.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/setup.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/setup.ts rename to x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/setup.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/use_request.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/use_request.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/use_request.ts rename to x-pack/plugins/fleet/public/applications/fleet/hooks/use_request/use_request.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_sorting.tsx b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_sorting.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_sorting.tsx rename to x-pack/plugins/fleet/public/applications/fleet/hooks/use_sorting.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_url_params.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_url_params.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_url_params.ts rename to x-pack/plugins/fleet/public/applications/fleet/hooks/use_url_params.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/index.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/index.tsx rename to x-pack/plugins/fleet/public/applications/fleet/index.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/default.tsx b/x-pack/plugins/fleet/public/applications/fleet/layouts/default.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/default.tsx rename to x-pack/plugins/fleet/public/applications/fleet/layouts/default.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/layouts/index.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/index.tsx rename to x-pack/plugins/fleet/public/applications/fleet/layouts/index.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/with_header.tsx b/x-pack/plugins/fleet/public/applications/fleet/layouts/with_header.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/with_header.tsx rename to x-pack/plugins/fleet/public/applications/fleet/layouts/with_header.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/without_header.tsx b/x-pack/plugins/fleet/public/applications/fleet/layouts/without_header.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/without_header.tsx rename to x-pack/plugins/fleet/public/applications/fleet/layouts/without_header.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/actions_menu.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/actions_menu.tsx similarity index 98% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/actions_menu.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/actions_menu.tsx index 55872aee5c3d3..4ded4b7786c8f 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/actions_menu.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/actions_menu.tsx @@ -9,7 +9,7 @@ import { EuiContextMenuItem, EuiPortal } from '@elastic/eui'; import { AgentPolicy } from '../../../types'; import { useCapabilities } from '../../../hooks'; import { ContextMenuActions } from '../../../components'; -import { AgentEnrollmentFlyout } from '../../fleet/components'; +import { AgentEnrollmentFlyout } from '../../agents/components'; import { AgentPolicyYamlFlyout } from './agent_policy_yaml_flyout'; import { AgentPolicyCopyProvider } from './agent_policy_copy_provider'; diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/agent_policy_copy_provider.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_copy_provider.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/agent_policy_copy_provider.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_copy_provider.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/agent_policy_delete_provider.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_delete_provider.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/agent_policy_delete_provider.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_delete_provider.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/agent_policy_form.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_form.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/agent_policy_form.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_form.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/agent_policy_yaml_flyout.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_yaml_flyout.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/agent_policy_yaml_flyout.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_yaml_flyout.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/confirm_deploy_modal.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/confirm_deploy_modal.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/confirm_deploy_modal.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/confirm_deploy_modal.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/danger_eui_context_menu_item.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/danger_eui_context_menu_item.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/danger_eui_context_menu_item.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/danger_eui_context_menu_item.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/index.ts b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/index.ts rename to x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/index.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/linked_agent_count.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/linked_agent_count.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/linked_agent_count.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/linked_agent_count.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/package_policy_delete_provider.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/package_policy_delete_provider.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/package_policy_delete_provider.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/package_policy_delete_provider.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/components/custom_package_policy.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/custom_package_policy.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/components/custom_package_policy.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/custom_package_policy.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/components/index.ts b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/components/index.ts rename to x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/index.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/components/layout.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/layout.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/components/layout.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/layout.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/components/package_policy_input_config.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/package_policy_input_config.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/components/package_policy_input_config.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/package_policy_input_config.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/components/package_policy_input_panel.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/package_policy_input_panel.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/components/package_policy_input_panel.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/package_policy_input_panel.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/components/package_policy_input_stream.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/package_policy_input_stream.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/components/package_policy_input_stream.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/package_policy_input_stream.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/components/package_policy_input_var_field.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/package_policy_input_var_field.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/components/package_policy_input_var_field.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/package_policy_input_var_field.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/index.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/index.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/index.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/services/has_invalid_but_required_var.test.ts b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/services/has_invalid_but_required_var.test.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/services/has_invalid_but_required_var.test.ts rename to x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/services/has_invalid_but_required_var.test.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/services/has_invalid_but_required_var.ts b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/services/has_invalid_but_required_var.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/services/has_invalid_but_required_var.ts rename to x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/services/has_invalid_but_required_var.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/services/index.ts b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/services/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/services/index.ts rename to x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/services/index.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/services/is_advanced_var.test.ts b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/services/is_advanced_var.test.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/services/is_advanced_var.test.ts rename to x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/services/is_advanced_var.test.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/services/is_advanced_var.ts b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/services/is_advanced_var.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/services/is_advanced_var.ts rename to x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/services/is_advanced_var.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/services/validate_package_policy.test.ts b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/services/validate_package_policy.test.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/services/validate_package_policy.test.ts rename to x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/services/validate_package_policy.test.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/services/validate_package_policy.ts b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/services/validate_package_policy.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/services/validate_package_policy.ts rename to x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/services/validate_package_policy.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/step_configure_package.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/step_configure_package.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/step_configure_package.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/step_configure_package.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/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 similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/step_define_package_policy.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/step_define_package_policy.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/step_select_agent_policy.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/step_select_agent_policy.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/step_select_agent_policy.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/step_select_agent_policy.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/step_select_package.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/step_select_package.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/step_select_package.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/step_select_package.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/types.ts b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/types.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/types.ts rename to x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/types.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/components/index.ts b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/details_page/components/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/components/index.ts rename to x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/details_page/components/index.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/components/package_policies/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/details_page/components/package_policies/index.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/components/package_policies/index.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/details_page/components/package_policies/index.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/components/package_policies/no_package_policies.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/details_page/components/package_policies/no_package_policies.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/components/package_policies/no_package_policies.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/details_page/components/package_policies/no_package_policies.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/components/package_policies/package_policies_table.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/details_page/components/package_policies/package_policies_table.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/components/package_policies/package_policies_table.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/details_page/components/package_policies/package_policies_table.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/components/settings/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/details_page/components/settings/index.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/components/settings/index.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/details_page/components/settings/index.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/hooks/index.ts b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/details_page/hooks/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/hooks/index.ts rename to x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/details_page/hooks/index.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/hooks/use_agent_status.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/details_page/hooks/use_agent_status.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/hooks/use_agent_status.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/details_page/hooks/use_agent_status.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/hooks/use_config.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/details_page/hooks/use_config.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/hooks/use_config.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/details_page/hooks/use_config.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/details_page/index.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/index.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/details_page/index.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/edit_package_policy_page/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/index.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/edit_package_policy_page/index.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/index.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/index.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/index.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/index.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/list_page/components/create_agent_policy.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/list_page/components/create_agent_policy.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/list_page/components/create_agent_policy.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/list_page/components/create_agent_policy.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/list_page/components/index.ts b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/list_page/components/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/list_page/components/index.ts rename to x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/list_page/components/index.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/list_page/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/list_page/index.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/list_page/index.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/list_page/index.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/components/actions_menu.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/actions_menu.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/components/actions_menu.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/actions_menu.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/components/agent_details.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_details.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/components/agent_details.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_details.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/components/agent_events_table.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_events_table.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/components/agent_events_table.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_events_table.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/components/helper.ts b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/helper.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/components/helper.ts rename to x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/helper.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/components/index.ts b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/components/index.ts rename to x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/index.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/components/metadata_flyout.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/metadata_flyout.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/components/metadata_flyout.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/metadata_flyout.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/components/metadata_form.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/metadata_form.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/components/metadata_form.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/metadata_form.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/components/type_labels.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/type_labels.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/components/type_labels.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/type_labels.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/hooks/index.ts b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/hooks/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/hooks/index.ts rename to x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/hooks/index.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/hooks/use_agent.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/hooks/use_agent.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/hooks/use_agent.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/hooks/use_agent.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/index.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/index.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/index.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_list_page/components/bulk_actions.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/bulk_actions.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_list_page/components/bulk_actions.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/bulk_actions.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_list_page/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/index.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_list_page/index.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/index.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/agent_policy_selection.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/components/agent_enrollment_flyout/agent_policy_selection.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/agent_policy_selection.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agents/components/agent_enrollment_flyout/agent_policy_selection.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/components/agent_enrollment_flyout/index.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/index.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agents/components/agent_enrollment_flyout/index.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/managed_instructions.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/components/agent_enrollment_flyout/managed_instructions.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/managed_instructions.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agents/components/agent_enrollment_flyout/managed_instructions.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/standalone_instructions.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/components/agent_enrollment_flyout/standalone_instructions.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/standalone_instructions.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agents/components/agent_enrollment_flyout/standalone_instructions.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/steps.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/components/agent_enrollment_flyout/steps.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/steps.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agents/components/agent_enrollment_flyout/steps.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_health.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/components/agent_health.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_health.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agents/components/agent_health.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_policy_package_badges.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/components/agent_policy_package_badges.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_policy_package_badges.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agents/components/agent_policy_package_badges.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_reassign_policy_flyout/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/components/agent_reassign_policy_flyout/index.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_reassign_policy_flyout/index.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agents/components/agent_reassign_policy_flyout/index.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_unenroll_modal/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/components/agent_unenroll_modal/index.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_unenroll_modal/index.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agents/components/agent_unenroll_modal/index.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_upgrade_modal/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/components/agent_upgrade_modal/index.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_upgrade_modal/index.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agents/components/agent_upgrade_modal/index.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/donut_chart.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/components/donut_chart.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/donut_chart.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agents/components/donut_chart.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/components/index.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/index.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agents/components/index.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/list_layout.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/components/list_layout.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/list_layout.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agents/components/list_layout.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/loading.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/components/loading.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/loading.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agents/components/loading.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/enrollment_token_list_page/components/confirm_delete_modal.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/enrollment_token_list_page/components/confirm_delete_modal.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/enrollment_token_list_page/components/confirm_delete_modal.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agents/enrollment_token_list_page/components/confirm_delete_modal.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/enrollment_token_list_page/components/new_enrollment_key_flyout.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/enrollment_token_list_page/components/new_enrollment_key_flyout.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/enrollment_token_list_page/components/new_enrollment_key_flyout.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agents/enrollment_token_list_page/components/new_enrollment_key_flyout.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/enrollment_token_list_page/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/enrollment_token_list_page/index.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/enrollment_token_list_page/index.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agents/enrollment_token_list_page/index.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/error_pages/components/no_data_layout.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/error_pages/components/no_data_layout.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/error_pages/components/no_data_layout.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agents/error_pages/components/no_data_layout.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/error_pages/enforce_security.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/error_pages/enforce_security.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/error_pages/enforce_security.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agents/error_pages/enforce_security.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/error_pages/invalid_license.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/error_pages/invalid_license.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/error_pages/invalid_license.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agents/error_pages/invalid_license.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/error_pages/no_access.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/error_pages/no_access.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/error_pages/no_access.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agents/error_pages/no_access.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/index.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/index.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agents/index.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/setup_page/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/setup_page/index.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/setup_page/index.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/agents/setup_page/index.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/data_stream/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/data_stream/index.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/data_stream/index.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/data_stream/index.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/data_stream/list_page/components/data_stream_row_actions.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/data_stream/list_page/components/data_stream_row_actions.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/data_stream/list_page/components/data_stream_row_actions.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/data_stream/list_page/components/data_stream_row_actions.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/data_stream/list_page/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/data_stream/list_page/index.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/data_stream/list_page/index.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/data_stream/list_page/index.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/components/assets_facet_group.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/epm/components/assets_facet_group.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/components/assets_facet_group.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/epm/components/assets_facet_group.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/components/icon_panel.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/epm/components/icon_panel.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/components/icon_panel.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/epm/components/icon_panel.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/components/icons.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/epm/components/icons.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/components/icons.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/epm/components/icons.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/components/package_card.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/epm/components/package_card.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/components/package_card.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/epm/components/package_card.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/components/package_list_grid.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/epm/components/package_list_grid.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/components/package_list_grid.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/epm/components/package_list_grid.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/components/release_badge.ts b/x-pack/plugins/fleet/public/applications/fleet/sections/epm/components/release_badge.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/components/release_badge.ts rename to x-pack/plugins/fleet/public/applications/fleet/sections/epm/components/release_badge.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/components/requirements.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/epm/components/requirements.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/components/requirements.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/epm/components/requirements.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/components/version.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/epm/components/version.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/components/version.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/epm/components/version.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/constants.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/epm/constants.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/constants.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/epm/constants.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/epm/hooks/index.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/index.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/epm/hooks/index.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/use_links.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/epm/hooks/use_links.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/use_links.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/epm/hooks/use_links.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/use_local_search.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/epm/hooks/use_local_search.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/use_local_search.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/epm/hooks/use_local_search.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/use_package_install.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/epm/hooks/use_package_install.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/use_package_install.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/epm/hooks/use_package_install.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/epm/index.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/index.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/epm/index.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/confirm_package_install.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/detail/confirm_package_install.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/confirm_package_install.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/detail/confirm_package_install.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/confirm_package_uninstall.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/detail/confirm_package_uninstall.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/confirm_package_uninstall.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/detail/confirm_package_uninstall.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/content.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/detail/content.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/content.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/detail/content.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/content_collapse.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/detail/content_collapse.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/content_collapse.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/detail/content_collapse.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/detail/index.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/index.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/detail/index.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/installation_button.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/detail/installation_button.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/installation_button.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/detail/installation_button.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/layout.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/detail/layout.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/layout.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/detail/layout.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/markdown_renderers.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/detail/markdown_renderers.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/markdown_renderers.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/detail/markdown_renderers.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/overview_panel.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/detail/overview_panel.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/overview_panel.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/detail/overview_panel.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/package_policies_panel.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/detail/package_policies_panel.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/package_policies_panel.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/detail/package_policies_panel.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/readme.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/detail/readme.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/readme.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/detail/readme.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/screenshots.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/detail/screenshots.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/screenshots.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/detail/screenshots.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/settings_panel.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/detail/settings_panel.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/settings_panel.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/detail/settings_panel.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/side_nav_links.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/detail/side_nav_links.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/side_nav_links.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/detail/side_nav_links.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/home/category_facets.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/home/category_facets.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/home/category_facets.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/home/category_facets.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/home/header.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/home/header.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/home/header.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/home/header.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/home/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/home/index.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/home/index.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/home/index.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/index.tsx similarity index 93% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/index.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/index.tsx index 3a0f2c3ea8d58..7642c1b3c8af2 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/index.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/index.tsx @@ -7,6 +7,6 @@ export { IngestManagerOverview } from './overview'; export { EPMApp } from './epm'; export { AgentPolicyApp } from './agent_policy'; export { DataStreamApp } from './data_stream'; -export { FleetApp } from './fleet'; +export { FleetApp } from './agents'; export type Section = 'overview' | 'epm' | 'agent_policy' | 'fleet' | 'data_stream'; diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/components/agent_policy_section.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/overview/components/agent_policy_section.tsx similarity index 98% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/components/agent_policy_section.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/overview/components/agent_policy_section.tsx index c49f99cfe8a04..6d26328cda4b9 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/components/agent_policy_section.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/overview/components/agent_policy_section.tsx @@ -18,7 +18,7 @@ import { OverviewStats } from './overview_stats'; import { SO_SEARCH_LIMIT } from '../../../constants'; import { useLink, useGetPackagePolicies } from '../../../hooks'; import { AgentPolicy } from '../../../types'; -import { Loading } from '../../fleet/components'; +import { Loading } from '../../agents/components'; export const OverviewPolicySection: React.FC<{ agentPolicies: AgentPolicy[] }> = ({ agentPolicies, diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/components/agent_section.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/overview/components/agent_section.tsx similarity index 98% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/components/agent_section.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/overview/components/agent_section.tsx index 5fbdf62d138d4..89d869c97621e 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/components/agent_section.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/overview/components/agent_section.tsx @@ -16,7 +16,7 @@ import { import { OverviewPanel } from './overview_panel'; import { OverviewStats } from './overview_stats'; import { useLink, useGetAgentStatus } from '../../../hooks'; -import { Loading } from '../../fleet/components'; +import { Loading } from '../../agents/components'; export const OverviewAgentSection = () => { const { getHref } = useLink(); diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/components/datastream_section.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/overview/components/datastream_section.tsx similarity index 98% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/components/datastream_section.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/overview/components/datastream_section.tsx index 3b645f7aa9d66..58f84e8671385 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/components/datastream_section.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/overview/components/datastream_section.tsx @@ -16,7 +16,7 @@ import { import { OverviewPanel } from './overview_panel'; import { OverviewStats } from './overview_stats'; import { useLink, useGetDataStreams, useStartDeps } from '../../../hooks'; -import { Loading } from '../../fleet/components'; +import { Loading } from '../../agents/components'; export const OverviewDatastreamSection: React.FC = () => { const { getHref } = useLink(); diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/components/integration_section.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/overview/components/integration_section.tsx similarity index 98% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/components/integration_section.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/overview/components/integration_section.tsx index 3f13b65a160d8..d69ec1f2aa1dc 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/components/integration_section.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/overview/components/integration_section.tsx @@ -16,7 +16,7 @@ import { import { OverviewPanel } from './overview_panel'; import { OverviewStats } from './overview_stats'; import { useLink, useGetPackages } from '../../../hooks'; -import { Loading } from '../../fleet/components'; +import { Loading } from '../../agents/components'; import { installationStatuses } from '../../../../../../common/constants'; export const OverviewIntegrationSection: React.FC = () => { diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/components/overview_panel.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/overview/components/overview_panel.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/components/overview_panel.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/overview/components/overview_panel.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/components/overview_stats.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/overview/components/overview_stats.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/components/overview_stats.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/overview/components/overview_stats.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/overview/index.tsx similarity index 98% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/index.tsx rename to x-pack/plugins/fleet/public/applications/fleet/sections/overview/index.tsx index c997caa90c653..1254d5db04d19 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/index.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/overview/index.tsx @@ -17,7 +17,7 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; import { WithHeaderLayout } from '../../layouts'; import { useGetAgentPolicies, useBreadcrumbs } from '../../hooks'; -import { AgentEnrollmentFlyout } from '../fleet/components'; +import { AgentEnrollmentFlyout } from '../agents/components'; import { OverviewAgentSection } from './components/agent_section'; import { OverviewPolicySection } from './components/agent_policy_section'; import { OverviewIntegrationSection } from './components/integration_section'; diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/services/index.ts b/x-pack/plugins/fleet/public/applications/fleet/services/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/services/index.ts rename to x-pack/plugins/fleet/public/applications/fleet/services/index.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/types/index.ts b/x-pack/plugins/fleet/public/applications/fleet/types/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/types/index.ts rename to x-pack/plugins/fleet/public/applications/fleet/types/index.ts diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/types/intra_app_route_state.ts b/x-pack/plugins/fleet/public/applications/fleet/types/intra_app_route_state.ts similarity index 100% rename from x-pack/plugins/ingest_manager/public/applications/ingest_manager/types/intra_app_route_state.ts rename to x-pack/plugins/fleet/public/applications/fleet/types/intra_app_route_state.ts diff --git a/x-pack/plugins/ingest_manager/public/assets/illustration_integrations_darkmode.svg b/x-pack/plugins/fleet/public/assets/illustration_integrations_darkmode.svg similarity index 100% rename from x-pack/plugins/ingest_manager/public/assets/illustration_integrations_darkmode.svg rename to x-pack/plugins/fleet/public/assets/illustration_integrations_darkmode.svg diff --git a/x-pack/plugins/ingest_manager/public/assets/illustration_integrations_lightmode.svg b/x-pack/plugins/fleet/public/assets/illustration_integrations_lightmode.svg similarity index 100% rename from x-pack/plugins/ingest_manager/public/assets/illustration_integrations_lightmode.svg rename to x-pack/plugins/fleet/public/assets/illustration_integrations_lightmode.svg diff --git a/x-pack/plugins/ingest_manager/public/index.ts b/x-pack/plugins/fleet/public/index.ts similarity index 65% rename from x-pack/plugins/ingest_manager/public/index.ts rename to x-pack/plugins/fleet/public/index.ts index a8a810b68735a..f974a8c3d3cc8 100644 --- a/x-pack/plugins/ingest_manager/public/index.ts +++ b/x-pack/plugins/fleet/public/index.ts @@ -16,9 +16,9 @@ export { CustomConfigurePackagePolicyContent, CustomConfigurePackagePolicyProps, registerPackagePolicyComponent, -} from './applications/ingest_manager/sections/agent_policy/create_package_policy_page/components/custom_package_policy'; +} from './applications/fleet/sections/agent_policy/create_package_policy_page/components/custom_package_policy'; -export type { NewPackagePolicy } from './applications/ingest_manager/types'; -export * from './applications/ingest_manager/types/intra_app_route_state'; +export type { NewPackagePolicy } from './applications/fleet/types'; +export * from './applications/fleet/types/intra_app_route_state'; -export { pagePathGetters } from './applications/ingest_manager/constants'; +export { pagePathGetters } from './applications/fleet/constants'; diff --git a/x-pack/plugins/ingest_manager/public/plugin.ts b/x-pack/plugins/fleet/public/plugin.ts similarity index 91% rename from x-pack/plugins/ingest_manager/public/plugin.ts rename to x-pack/plugins/fleet/public/plugin.ts index 6847a39819e8e..2e7cbb9cb86ab 100644 --- a/x-pack/plugins/ingest_manager/public/plugin.ts +++ b/x-pack/plugins/fleet/public/plugin.ts @@ -19,18 +19,18 @@ import { } from '../../../../src/plugins/home/public'; import { LicensingPluginSetup } from '../../licensing/public'; import { PLUGIN_ID, CheckPermissionsResponse, PostIngestSetupResponse } from '../common'; -import { BASE_PATH } from './applications/ingest_manager/constants'; +import { BASE_PATH } from './applications/fleet/constants'; import { IngestManagerConfigType } from '../common/types'; import { setupRouteService, appRoutesService } from '../common'; -import { licenseService } from './applications/ingest_manager/hooks/use_license'; -import { setHttpClient } from './applications/ingest_manager/hooks/use_request/use_request'; +import { licenseService } from './applications/fleet/hooks/use_license'; +import { setHttpClient } from './applications/fleet/hooks/use_request/use_request'; import { TutorialDirectoryNotice, TutorialDirectoryHeaderLink, TutorialModuleNotice, -} from './applications/ingest_manager/components/home_integration'; -import { registerPackagePolicyComponent } from './applications/ingest_manager/sections/agent_policy/create_package_policy_page/components/custom_package_policy'; +} from './applications/fleet/components/home_integration'; +import { registerPackagePolicyComponent } from './applications/fleet/sections/agent_policy/create_package_policy_page/components/custom_package_policy'; export { IngestManagerConfigType } from '../common/types'; @@ -91,7 +91,7 @@ export class IngestManagerPlugin IngestManagerStartDeps, IngestManagerStart ]; - const { renderApp, teardownIngestManager } = await import('./applications/ingest_manager'); + const { renderApp, teardownIngestManager } = await import('./applications/fleet/'); const unmount = renderApp(coreStart, params, deps, startDeps, config, kibanaVersion); return () => { diff --git a/x-pack/plugins/ingest_manager/scripts/dev_agent/index.js b/x-pack/plugins/fleet/scripts/dev_agent/index.js similarity index 100% rename from x-pack/plugins/ingest_manager/scripts/dev_agent/index.js rename to x-pack/plugins/fleet/scripts/dev_agent/index.js diff --git a/x-pack/plugins/ingest_manager/scripts/dev_agent/script.ts b/x-pack/plugins/fleet/scripts/dev_agent/script.ts similarity index 100% rename from x-pack/plugins/ingest_manager/scripts/dev_agent/script.ts rename to x-pack/plugins/fleet/scripts/dev_agent/script.ts diff --git a/x-pack/plugins/ingest_manager/scripts/readme.md b/x-pack/plugins/fleet/scripts/readme.md similarity index 100% rename from x-pack/plugins/ingest_manager/scripts/readme.md rename to x-pack/plugins/fleet/scripts/readme.md diff --git a/x-pack/plugins/ingest_manager/server/collectors/agent_collectors.ts b/x-pack/plugins/fleet/server/collectors/agent_collectors.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/collectors/agent_collectors.ts rename to x-pack/plugins/fleet/server/collectors/agent_collectors.ts diff --git a/x-pack/plugins/ingest_manager/server/collectors/config_collectors.ts b/x-pack/plugins/fleet/server/collectors/config_collectors.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/collectors/config_collectors.ts rename to x-pack/plugins/fleet/server/collectors/config_collectors.ts diff --git a/x-pack/plugins/ingest_manager/server/collectors/helpers.ts b/x-pack/plugins/fleet/server/collectors/helpers.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/collectors/helpers.ts rename to x-pack/plugins/fleet/server/collectors/helpers.ts diff --git a/x-pack/plugins/ingest_manager/server/collectors/package_collectors.ts b/x-pack/plugins/fleet/server/collectors/package_collectors.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/collectors/package_collectors.ts rename to x-pack/plugins/fleet/server/collectors/package_collectors.ts diff --git a/x-pack/plugins/ingest_manager/server/collectors/register.ts b/x-pack/plugins/fleet/server/collectors/register.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/collectors/register.ts rename to x-pack/plugins/fleet/server/collectors/register.ts diff --git a/x-pack/plugins/ingest_manager/server/constants/index.ts b/x-pack/plugins/fleet/server/constants/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/constants/index.ts rename to x-pack/plugins/fleet/server/constants/index.ts diff --git a/x-pack/plugins/ingest_manager/server/errors/handlers.test.ts b/x-pack/plugins/fleet/server/errors/handlers.test.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/errors/handlers.test.ts rename to x-pack/plugins/fleet/server/errors/handlers.test.ts diff --git a/x-pack/plugins/ingest_manager/server/errors/handlers.ts b/x-pack/plugins/fleet/server/errors/handlers.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/errors/handlers.ts rename to x-pack/plugins/fleet/server/errors/handlers.ts diff --git a/x-pack/plugins/ingest_manager/server/errors/index.ts b/x-pack/plugins/fleet/server/errors/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/errors/index.ts rename to x-pack/plugins/fleet/server/errors/index.ts diff --git a/x-pack/plugins/ingest_manager/server/index.ts b/x-pack/plugins/fleet/server/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/index.ts rename to x-pack/plugins/fleet/server/index.ts diff --git a/x-pack/plugins/ingest_manager/server/integration_tests/router.test.ts b/x-pack/plugins/fleet/server/integration_tests/router.test.ts similarity index 97% rename from x-pack/plugins/ingest_manager/server/integration_tests/router.test.ts rename to x-pack/plugins/fleet/server/integration_tests/router.test.ts index 46b10ff381a60..c110ad23b6191 100644 --- a/x-pack/plugins/ingest_manager/server/integration_tests/router.test.ts +++ b/x-pack/plugins/fleet/server/integration_tests/router.test.ts @@ -21,7 +21,7 @@ function createXPackRoot(config: {} = {}) { scanDirs: [], paths: [ resolve(__dirname, '../../../../../x-pack/plugins/encrypted_saved_objects'), - resolve(__dirname, '../../../../../x-pack/plugins/ingest_manager'), + resolve(__dirname, '../../../../../x-pack/plugins/fleet'), resolve(__dirname, '../../../../../x-pack/plugins/licensing'), ], }, @@ -94,7 +94,7 @@ describe('ingestManager', () => { // For now, only the manager routes (/agent_policies & /package_policies) are added // EPM and ingest will be conditionally added when we enable these lines - // https://github.com/jfsiii/kibana/blob/f73b54ebb7e0f6fc00efd8a6800a01eb2d9fb772/x-pack/plugins/ingest_manager/server/plugin.ts#L84 + // https://github.com/jfsiii/kibana/blob/f73b54ebb7e0f6fc00efd8a6800a01eb2d9fb772/x-pack/plugins/fleet/server/plugin.ts#L84 // adding tests to confirm the Fleet & EPM routes are never added describe('manager and EPM; no Fleet', () => { diff --git a/x-pack/plugins/ingest_manager/server/mocks.ts b/x-pack/plugins/fleet/server/mocks.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/mocks.ts rename to x-pack/plugins/fleet/server/mocks.ts diff --git a/x-pack/plugins/ingest_manager/server/plugin.ts b/x-pack/plugins/fleet/server/plugin.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/plugin.ts rename to x-pack/plugins/fleet/server/plugin.ts diff --git a/x-pack/plugins/ingest_manager/server/routes/agent/acks_handlers.test.ts b/x-pack/plugins/fleet/server/routes/agent/acks_handlers.test.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/routes/agent/acks_handlers.test.ts rename to x-pack/plugins/fleet/server/routes/agent/acks_handlers.test.ts diff --git a/x-pack/plugins/ingest_manager/server/routes/agent/acks_handlers.ts b/x-pack/plugins/fleet/server/routes/agent/acks_handlers.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/routes/agent/acks_handlers.ts rename to x-pack/plugins/fleet/server/routes/agent/acks_handlers.ts diff --git a/x-pack/plugins/ingest_manager/server/routes/agent/actions_handlers.test.ts b/x-pack/plugins/fleet/server/routes/agent/actions_handlers.test.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/routes/agent/actions_handlers.test.ts rename to x-pack/plugins/fleet/server/routes/agent/actions_handlers.test.ts diff --git a/x-pack/plugins/ingest_manager/server/routes/agent/actions_handlers.ts b/x-pack/plugins/fleet/server/routes/agent/actions_handlers.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/routes/agent/actions_handlers.ts rename to x-pack/plugins/fleet/server/routes/agent/actions_handlers.ts diff --git a/x-pack/plugins/ingest_manager/server/routes/agent/handlers.ts b/x-pack/plugins/fleet/server/routes/agent/handlers.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/routes/agent/handlers.ts rename to x-pack/plugins/fleet/server/routes/agent/handlers.ts diff --git a/x-pack/plugins/ingest_manager/server/routes/agent/index.ts b/x-pack/plugins/fleet/server/routes/agent/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/routes/agent/index.ts rename to x-pack/plugins/fleet/server/routes/agent/index.ts diff --git a/x-pack/plugins/ingest_manager/server/routes/agent/unenroll_handler.ts b/x-pack/plugins/fleet/server/routes/agent/unenroll_handler.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/routes/agent/unenroll_handler.ts rename to x-pack/plugins/fleet/server/routes/agent/unenroll_handler.ts diff --git a/x-pack/plugins/ingest_manager/server/routes/agent/upgrade_handler.ts b/x-pack/plugins/fleet/server/routes/agent/upgrade_handler.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/routes/agent/upgrade_handler.ts rename to x-pack/plugins/fleet/server/routes/agent/upgrade_handler.ts diff --git a/x-pack/plugins/ingest_manager/server/routes/agent_policy/handlers.ts b/x-pack/plugins/fleet/server/routes/agent_policy/handlers.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/routes/agent_policy/handlers.ts rename to x-pack/plugins/fleet/server/routes/agent_policy/handlers.ts diff --git a/x-pack/plugins/ingest_manager/server/routes/agent_policy/index.ts b/x-pack/plugins/fleet/server/routes/agent_policy/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/routes/agent_policy/index.ts rename to x-pack/plugins/fleet/server/routes/agent_policy/index.ts diff --git a/x-pack/plugins/ingest_manager/server/routes/app/index.ts b/x-pack/plugins/fleet/server/routes/app/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/routes/app/index.ts rename to x-pack/plugins/fleet/server/routes/app/index.ts diff --git a/x-pack/plugins/ingest_manager/server/routes/data_streams/handlers.ts b/x-pack/plugins/fleet/server/routes/data_streams/handlers.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/routes/data_streams/handlers.ts rename to x-pack/plugins/fleet/server/routes/data_streams/handlers.ts diff --git a/x-pack/plugins/ingest_manager/server/routes/data_streams/index.ts b/x-pack/plugins/fleet/server/routes/data_streams/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/routes/data_streams/index.ts rename to x-pack/plugins/fleet/server/routes/data_streams/index.ts diff --git a/x-pack/plugins/ingest_manager/server/routes/enrollment_api_key/handler.ts b/x-pack/plugins/fleet/server/routes/enrollment_api_key/handler.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/routes/enrollment_api_key/handler.ts rename to x-pack/plugins/fleet/server/routes/enrollment_api_key/handler.ts diff --git a/x-pack/plugins/ingest_manager/server/routes/enrollment_api_key/index.ts b/x-pack/plugins/fleet/server/routes/enrollment_api_key/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/routes/enrollment_api_key/index.ts rename to x-pack/plugins/fleet/server/routes/enrollment_api_key/index.ts diff --git a/x-pack/plugins/ingest_manager/server/routes/epm/handlers.ts b/x-pack/plugins/fleet/server/routes/epm/handlers.ts similarity index 98% rename from x-pack/plugins/ingest_manager/server/routes/epm/handlers.ts rename to x-pack/plugins/fleet/server/routes/epm/handlers.ts index 198a54ca84125..1d221b8b1eead 100644 --- a/x-pack/plugins/ingest_manager/server/routes/epm/handlers.ts +++ b/x-pack/plugins/fleet/server/routes/epm/handlers.ts @@ -35,8 +35,7 @@ import { getPackageInfo, handleInstallPackageFailure, isBulkInstallError, - installPackageFromRegistry, - installPackageByUpload, + installPackage, removeInstallation, getLimitedPackages, getInstallationObject, @@ -149,7 +148,8 @@ export const installPackageFromRegistryHandler: RequestHandler< const { pkgName, pkgVersion } = splitPkgKey(pkgkey); const installedPkg = await getInstallationObject({ savedObjectsClient, pkgName }); try { - const res = await installPackageFromRegistry({ + const res = await installPackage({ + installSource: 'registry', savedObjectsClient, pkgkey, callCluster, @@ -224,7 +224,8 @@ export const installPackageByUploadHandler: RequestHandler< const contentType = request.headers['content-type'] as string; // from types it could also be string[] or undefined but this is checked later const archiveBuffer = Buffer.from(request.body); try { - const res = await installPackageByUpload({ + const res = await installPackage({ + installSource: 'upload', savedObjectsClient, callCluster, archiveBuffer, diff --git a/x-pack/plugins/ingest_manager/server/routes/epm/index.ts b/x-pack/plugins/fleet/server/routes/epm/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/routes/epm/index.ts rename to x-pack/plugins/fleet/server/routes/epm/index.ts diff --git a/x-pack/plugins/ingest_manager/server/routes/index.ts b/x-pack/plugins/fleet/server/routes/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/routes/index.ts rename to x-pack/plugins/fleet/server/routes/index.ts diff --git a/x-pack/plugins/ingest_manager/server/routes/install_script/index.ts b/x-pack/plugins/fleet/server/routes/install_script/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/routes/install_script/index.ts rename to x-pack/plugins/fleet/server/routes/install_script/index.ts diff --git a/x-pack/plugins/ingest_manager/server/routes/limited_concurrency.test.ts b/x-pack/plugins/fleet/server/routes/limited_concurrency.test.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/routes/limited_concurrency.test.ts rename to x-pack/plugins/fleet/server/routes/limited_concurrency.test.ts diff --git a/x-pack/plugins/ingest_manager/server/routes/limited_concurrency.ts b/x-pack/plugins/fleet/server/routes/limited_concurrency.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/routes/limited_concurrency.ts rename to x-pack/plugins/fleet/server/routes/limited_concurrency.ts diff --git a/x-pack/plugins/ingest_manager/server/routes/output/handler.ts b/x-pack/plugins/fleet/server/routes/output/handler.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/routes/output/handler.ts rename to x-pack/plugins/fleet/server/routes/output/handler.ts diff --git a/x-pack/plugins/ingest_manager/server/routes/output/index.ts b/x-pack/plugins/fleet/server/routes/output/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/routes/output/index.ts rename to x-pack/plugins/fleet/server/routes/output/index.ts diff --git a/x-pack/plugins/ingest_manager/server/routes/package_policy/handlers.test.ts b/x-pack/plugins/fleet/server/routes/package_policy/handlers.test.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/routes/package_policy/handlers.test.ts rename to x-pack/plugins/fleet/server/routes/package_policy/handlers.test.ts diff --git a/x-pack/plugins/ingest_manager/server/routes/package_policy/handlers.ts b/x-pack/plugins/fleet/server/routes/package_policy/handlers.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/routes/package_policy/handlers.ts rename to x-pack/plugins/fleet/server/routes/package_policy/handlers.ts diff --git a/x-pack/plugins/ingest_manager/server/routes/package_policy/index.ts b/x-pack/plugins/fleet/server/routes/package_policy/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/routes/package_policy/index.ts rename to x-pack/plugins/fleet/server/routes/package_policy/index.ts diff --git a/x-pack/plugins/ingest_manager/server/routes/settings/index.ts b/x-pack/plugins/fleet/server/routes/settings/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/routes/settings/index.ts rename to x-pack/plugins/fleet/server/routes/settings/index.ts diff --git a/x-pack/plugins/ingest_manager/server/routes/setup/handlers.test.ts b/x-pack/plugins/fleet/server/routes/setup/handlers.test.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/routes/setup/handlers.test.ts rename to x-pack/plugins/fleet/server/routes/setup/handlers.test.ts diff --git a/x-pack/plugins/ingest_manager/server/routes/setup/handlers.ts b/x-pack/plugins/fleet/server/routes/setup/handlers.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/routes/setup/handlers.ts rename to x-pack/plugins/fleet/server/routes/setup/handlers.ts diff --git a/x-pack/plugins/ingest_manager/server/routes/setup/index.ts b/x-pack/plugins/fleet/server/routes/setup/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/routes/setup/index.ts rename to x-pack/plugins/fleet/server/routes/setup/index.ts diff --git a/x-pack/plugins/ingest_manager/server/saved_objects/index.ts b/x-pack/plugins/fleet/server/saved_objects/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/saved_objects/index.ts rename to x-pack/plugins/fleet/server/saved_objects/index.ts diff --git a/x-pack/plugins/ingest_manager/server/saved_objects/migrations/to_v7_10_0.ts b/x-pack/plugins/fleet/server/saved_objects/migrations/to_v7_10_0.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/saved_objects/migrations/to_v7_10_0.ts rename to x-pack/plugins/fleet/server/saved_objects/migrations/to_v7_10_0.ts diff --git a/x-pack/plugins/ingest_manager/server/services/agent_policy.test.ts b/x-pack/plugins/fleet/server/services/agent_policy.test.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/agent_policy.test.ts rename to x-pack/plugins/fleet/server/services/agent_policy.test.ts diff --git a/x-pack/plugins/ingest_manager/server/services/agent_policy.ts b/x-pack/plugins/fleet/server/services/agent_policy.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/agent_policy.ts rename to x-pack/plugins/fleet/server/services/agent_policy.ts diff --git a/x-pack/plugins/ingest_manager/server/services/agent_policy_update.ts b/x-pack/plugins/fleet/server/services/agent_policy_update.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/agent_policy_update.ts rename to x-pack/plugins/fleet/server/services/agent_policy_update.ts diff --git a/x-pack/plugins/ingest_manager/server/services/agents/acks.test.ts b/x-pack/plugins/fleet/server/services/agents/acks.test.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/agents/acks.test.ts rename to x-pack/plugins/fleet/server/services/agents/acks.test.ts diff --git a/x-pack/plugins/ingest_manager/server/services/agents/acks.ts b/x-pack/plugins/fleet/server/services/agents/acks.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/agents/acks.ts rename to x-pack/plugins/fleet/server/services/agents/acks.ts diff --git a/x-pack/plugins/ingest_manager/server/services/agents/actions.test.ts b/x-pack/plugins/fleet/server/services/agents/actions.test.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/agents/actions.test.ts rename to x-pack/plugins/fleet/server/services/agents/actions.test.ts diff --git a/x-pack/plugins/ingest_manager/server/services/agents/actions.ts b/x-pack/plugins/fleet/server/services/agents/actions.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/agents/actions.ts rename to x-pack/plugins/fleet/server/services/agents/actions.ts diff --git a/x-pack/plugins/ingest_manager/server/services/agents/authenticate.test.ts b/x-pack/plugins/fleet/server/services/agents/authenticate.test.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/agents/authenticate.test.ts rename to x-pack/plugins/fleet/server/services/agents/authenticate.test.ts diff --git a/x-pack/plugins/ingest_manager/server/services/agents/authenticate.ts b/x-pack/plugins/fleet/server/services/agents/authenticate.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/agents/authenticate.ts rename to x-pack/plugins/fleet/server/services/agents/authenticate.ts diff --git a/x-pack/plugins/ingest_manager/server/services/agents/checkin/index.ts b/x-pack/plugins/fleet/server/services/agents/checkin/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/agents/checkin/index.ts rename to x-pack/plugins/fleet/server/services/agents/checkin/index.ts diff --git a/x-pack/plugins/ingest_manager/server/services/agents/checkin/rxjs_utils.test.ts b/x-pack/plugins/fleet/server/services/agents/checkin/rxjs_utils.test.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/agents/checkin/rxjs_utils.test.ts rename to x-pack/plugins/fleet/server/services/agents/checkin/rxjs_utils.test.ts diff --git a/x-pack/plugins/ingest_manager/server/services/agents/checkin/rxjs_utils.ts b/x-pack/plugins/fleet/server/services/agents/checkin/rxjs_utils.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/agents/checkin/rxjs_utils.ts rename to x-pack/plugins/fleet/server/services/agents/checkin/rxjs_utils.ts diff --git a/x-pack/plugins/ingest_manager/server/services/agents/checkin/state.ts b/x-pack/plugins/fleet/server/services/agents/checkin/state.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/agents/checkin/state.ts rename to x-pack/plugins/fleet/server/services/agents/checkin/state.ts diff --git a/x-pack/plugins/ingest_manager/server/services/agents/checkin/state_connected_agents.ts b/x-pack/plugins/fleet/server/services/agents/checkin/state_connected_agents.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/agents/checkin/state_connected_agents.ts rename to x-pack/plugins/fleet/server/services/agents/checkin/state_connected_agents.ts diff --git a/x-pack/plugins/ingest_manager/server/services/agents/checkin/state_new_actions.test.ts b/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.test.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/agents/checkin/state_new_actions.test.ts rename to x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.test.ts diff --git a/x-pack/plugins/ingest_manager/server/services/agents/checkin/state_new_actions.ts b/x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/agents/checkin/state_new_actions.ts rename to x-pack/plugins/fleet/server/services/agents/checkin/state_new_actions.ts diff --git a/x-pack/plugins/ingest_manager/server/services/agents/crud.ts b/x-pack/plugins/fleet/server/services/agents/crud.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/agents/crud.ts rename to x-pack/plugins/fleet/server/services/agents/crud.ts diff --git a/x-pack/plugins/ingest_manager/server/services/agents/enroll.test.ts b/x-pack/plugins/fleet/server/services/agents/enroll.test.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/agents/enroll.test.ts rename to x-pack/plugins/fleet/server/services/agents/enroll.test.ts diff --git a/x-pack/plugins/ingest_manager/server/services/agents/enroll.ts b/x-pack/plugins/fleet/server/services/agents/enroll.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/agents/enroll.ts rename to x-pack/plugins/fleet/server/services/agents/enroll.ts diff --git a/x-pack/plugins/ingest_manager/server/services/agents/events.ts b/x-pack/plugins/fleet/server/services/agents/events.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/agents/events.ts rename to x-pack/plugins/fleet/server/services/agents/events.ts diff --git a/x-pack/plugins/ingest_manager/server/services/agents/index.ts b/x-pack/plugins/fleet/server/services/agents/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/agents/index.ts rename to x-pack/plugins/fleet/server/services/agents/index.ts diff --git a/x-pack/plugins/ingest_manager/server/services/agents/reassign.ts b/x-pack/plugins/fleet/server/services/agents/reassign.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/agents/reassign.ts rename to x-pack/plugins/fleet/server/services/agents/reassign.ts diff --git a/x-pack/plugins/ingest_manager/server/services/agents/saved_objects.ts b/x-pack/plugins/fleet/server/services/agents/saved_objects.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/agents/saved_objects.ts rename to x-pack/plugins/fleet/server/services/agents/saved_objects.ts diff --git a/x-pack/plugins/ingest_manager/server/services/agents/setup.ts b/x-pack/plugins/fleet/server/services/agents/setup.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/agents/setup.ts rename to x-pack/plugins/fleet/server/services/agents/setup.ts diff --git a/x-pack/plugins/ingest_manager/server/services/agents/status.test.ts b/x-pack/plugins/fleet/server/services/agents/status.test.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/agents/status.test.ts rename to x-pack/plugins/fleet/server/services/agents/status.test.ts diff --git a/x-pack/plugins/ingest_manager/server/services/agents/status.ts b/x-pack/plugins/fleet/server/services/agents/status.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/agents/status.ts rename to x-pack/plugins/fleet/server/services/agents/status.ts diff --git a/x-pack/plugins/ingest_manager/server/services/agents/unenroll.ts b/x-pack/plugins/fleet/server/services/agents/unenroll.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/agents/unenroll.ts rename to x-pack/plugins/fleet/server/services/agents/unenroll.ts diff --git a/x-pack/plugins/ingest_manager/server/services/agents/update.ts b/x-pack/plugins/fleet/server/services/agents/update.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/agents/update.ts rename to x-pack/plugins/fleet/server/services/agents/update.ts diff --git a/x-pack/plugins/ingest_manager/server/services/agents/upgrade.ts b/x-pack/plugins/fleet/server/services/agents/upgrade.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/agents/upgrade.ts rename to x-pack/plugins/fleet/server/services/agents/upgrade.ts diff --git a/x-pack/plugins/ingest_manager/server/services/api_keys/enrollment_api_key.ts b/x-pack/plugins/fleet/server/services/api_keys/enrollment_api_key.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/api_keys/enrollment_api_key.ts rename to x-pack/plugins/fleet/server/services/api_keys/enrollment_api_key.ts diff --git a/x-pack/plugins/ingest_manager/server/services/api_keys/index.ts b/x-pack/plugins/fleet/server/services/api_keys/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/api_keys/index.ts rename to x-pack/plugins/fleet/server/services/api_keys/index.ts diff --git a/x-pack/plugins/ingest_manager/server/services/api_keys/security.ts b/x-pack/plugins/fleet/server/services/api_keys/security.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/api_keys/security.ts rename to x-pack/plugins/fleet/server/services/api_keys/security.ts diff --git a/x-pack/plugins/ingest_manager/server/services/app_context.ts b/x-pack/plugins/fleet/server/services/app_context.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/app_context.ts rename to x-pack/plugins/fleet/server/services/app_context.ts diff --git a/x-pack/plugins/ingest_manager/server/services/config.ts b/x-pack/plugins/fleet/server/services/config.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/config.ts rename to x-pack/plugins/fleet/server/services/config.ts diff --git a/x-pack/plugins/ingest_manager/server/services/epm/agent/agent.test.ts b/x-pack/plugins/fleet/server/services/epm/agent/agent.test.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/agent/agent.test.ts rename to x-pack/plugins/fleet/server/services/epm/agent/agent.test.ts diff --git a/x-pack/plugins/ingest_manager/server/services/epm/agent/agent.ts b/x-pack/plugins/fleet/server/services/epm/agent/agent.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/agent/agent.ts rename to x-pack/plugins/fleet/server/services/epm/agent/agent.ts diff --git a/x-pack/plugins/ingest_manager/server/services/epm/archive/cache.ts b/x-pack/plugins/fleet/server/services/epm/archive/cache.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/archive/cache.ts rename to x-pack/plugins/fleet/server/services/epm/archive/cache.ts diff --git a/x-pack/plugins/ingest_manager/server/services/epm/archive/index.ts b/x-pack/plugins/fleet/server/services/epm/archive/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/archive/index.ts rename to x-pack/plugins/fleet/server/services/epm/archive/index.ts diff --git a/x-pack/plugins/ingest_manager/server/services/epm/archive/validation.ts b/x-pack/plugins/fleet/server/services/epm/archive/validation.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/archive/validation.ts rename to x-pack/plugins/fleet/server/services/epm/archive/validation.ts diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/ilm/install.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/ilm/install.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/ilm/install.ts rename to x-pack/plugins/fleet/server/services/epm/elasticsearch/ilm/install.ts diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/index.test.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/index.test.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/index.test.ts rename to x-pack/plugins/fleet/server/services/epm/elasticsearch/index.test.ts diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/index.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/index.ts rename to x-pack/plugins/fleet/server/services/epm/elasticsearch/index.ts diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/ingest_pipeline/index.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/ingest_pipeline/index.ts rename to x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/index.ts diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/ingest_pipeline/ingest_pipelines.test.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/ingest_pipelines.test.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/ingest_pipeline/ingest_pipelines.test.ts rename to x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/ingest_pipelines.test.ts diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/ingest_pipeline/install.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/install.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/ingest_pipeline/install.ts rename to x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/install.ts diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/ingest_pipeline/remove.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/remove.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/ingest_pipeline/remove.ts rename to x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/remove.ts diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/ingest_pipeline/tests/ingest_pipeline_template.json b/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/tests/ingest_pipeline_template.json similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/ingest_pipeline/tests/ingest_pipeline_template.json rename to x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/tests/ingest_pipeline_template.json diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/ingest_pipeline/tests/ingest_pipelines/no_replacement.json b/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/tests/ingest_pipelines/no_replacement.json similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/ingest_pipeline/tests/ingest_pipelines/no_replacement.json rename to x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/tests/ingest_pipelines/no_replacement.json diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/ingest_pipeline/tests/ingest_pipelines/no_replacement.yml b/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/tests/ingest_pipelines/no_replacement.yml similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/ingest_pipeline/tests/ingest_pipelines/no_replacement.yml rename to x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/tests/ingest_pipelines/no_replacement.yml diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/ingest_pipeline/tests/ingest_pipelines/real_input_beats.json b/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/tests/ingest_pipelines/real_input_beats.json similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/ingest_pipeline/tests/ingest_pipelines/real_input_beats.json rename to x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/tests/ingest_pipelines/real_input_beats.json diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/ingest_pipeline/tests/ingest_pipelines/real_input_beats.yml b/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/tests/ingest_pipelines/real_input_beats.yml similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/ingest_pipeline/tests/ingest_pipelines/real_input_beats.yml rename to x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/tests/ingest_pipelines/real_input_beats.yml diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/ingest_pipeline/tests/ingest_pipelines/real_input_standard.json b/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/tests/ingest_pipelines/real_input_standard.json similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/ingest_pipeline/tests/ingest_pipelines/real_input_standard.json rename to x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/tests/ingest_pipelines/real_input_standard.json diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/ingest_pipeline/tests/ingest_pipelines/real_input_standard.yml b/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/tests/ingest_pipelines/real_input_standard.yml similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/ingest_pipeline/tests/ingest_pipelines/real_input_standard.yml rename to x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/tests/ingest_pipelines/real_input_standard.yml diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/ingest_pipeline/tests/ingest_pipelines/real_output.json b/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/tests/ingest_pipelines/real_output.json similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/ingest_pipeline/tests/ingest_pipelines/real_output.json rename to x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/tests/ingest_pipelines/real_output.json diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/ingest_pipeline/tests/ingest_pipelines/real_output.yml b/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/tests/ingest_pipelines/real_output.yml similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/ingest_pipeline/tests/ingest_pipelines/real_output.yml rename to x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/tests/ingest_pipelines/real_output.yml diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/__snapshots__/template.test.ts.snap b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/__snapshots__/template.test.ts.snap similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/__snapshots__/template.test.ts.snap rename to x-pack/plugins/fleet/server/services/epm/elasticsearch/template/__snapshots__/template.test.ts.snap diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/install.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.ts similarity index 98% rename from x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/install.ts rename to x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.ts index 6a4d1ca0e1d0a..25d412b685904 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/install.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.ts @@ -219,7 +219,7 @@ function buildComponentTemplates(registryElasticsearch: RegistryElasticsearch | // temporary change until https://github.com/elastic/elasticsearch/issues/58956 is resolved // hopefully we'll be able to remove the entire properties section once that issue is resolved properties: { - // if the timestamp_field changes here: https://github.com/elastic/kibana/blob/master/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/template.ts#L309 + // if the timestamp_field changes here: https://github.com/elastic/kibana/blob/master/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.ts#L309 // we'll need to update this as well '@timestamp': { type: 'date', diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/template.test.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.test.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/template.test.ts rename to x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.test.ts diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/template.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/template.ts rename to x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.ts diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/transform/common.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/common.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/transform/common.ts rename to x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/common.ts diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/transform/install.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/install.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/transform/install.ts rename to x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/install.ts diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/transform/remove.test.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/remove.test.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/transform/remove.test.ts rename to x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/remove.test.ts diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/transform/remove.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/remove.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/transform/remove.ts rename to x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/remove.ts diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/transform/transform.test.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/transform.test.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/transform/transform.test.ts rename to x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/transform.test.ts diff --git a/x-pack/plugins/ingest_manager/server/services/epm/fields/__snapshots__/field.test.ts.snap b/x-pack/plugins/fleet/server/services/epm/fields/__snapshots__/field.test.ts.snap similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/fields/__snapshots__/field.test.ts.snap rename to x-pack/plugins/fleet/server/services/epm/fields/__snapshots__/field.test.ts.snap diff --git a/x-pack/plugins/ingest_manager/server/services/epm/fields/field.test.ts b/x-pack/plugins/fleet/server/services/epm/fields/field.test.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/fields/field.test.ts rename to x-pack/plugins/fleet/server/services/epm/fields/field.test.ts diff --git a/x-pack/plugins/ingest_manager/server/services/epm/fields/field.ts b/x-pack/plugins/fleet/server/services/epm/fields/field.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/fields/field.ts rename to x-pack/plugins/fleet/server/services/epm/fields/field.ts diff --git a/x-pack/plugins/ingest_manager/server/services/epm/fields/tests/base.yml b/x-pack/plugins/fleet/server/services/epm/fields/tests/base.yml similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/fields/tests/base.yml rename to x-pack/plugins/fleet/server/services/epm/fields/tests/base.yml diff --git a/x-pack/plugins/ingest_manager/server/services/epm/fields/tests/coredns.logs.yml b/x-pack/plugins/fleet/server/services/epm/fields/tests/coredns.logs.yml similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/fields/tests/coredns.logs.yml rename to x-pack/plugins/fleet/server/services/epm/fields/tests/coredns.logs.yml diff --git a/x-pack/plugins/ingest_manager/server/services/epm/fields/tests/system.yml b/x-pack/plugins/fleet/server/services/epm/fields/tests/system.yml similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/fields/tests/system.yml rename to x-pack/plugins/fleet/server/services/epm/fields/tests/system.yml diff --git a/x-pack/plugins/ingest_manager/server/services/epm/kibana/assets/install.ts b/x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/kibana/assets/install.ts rename to x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts diff --git a/x-pack/plugins/ingest_manager/server/services/epm/kibana/index_pattern/__snapshots__/install.test.ts.snap b/x-pack/plugins/fleet/server/services/epm/kibana/index_pattern/__snapshots__/install.test.ts.snap similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/kibana/index_pattern/__snapshots__/install.test.ts.snap rename to x-pack/plugins/fleet/server/services/epm/kibana/index_pattern/__snapshots__/install.test.ts.snap diff --git a/x-pack/plugins/ingest_manager/server/services/epm/kibana/index_pattern/install.test.ts b/x-pack/plugins/fleet/server/services/epm/kibana/index_pattern/install.test.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/kibana/index_pattern/install.test.ts rename to x-pack/plugins/fleet/server/services/epm/kibana/index_pattern/install.test.ts diff --git a/x-pack/plugins/ingest_manager/server/services/epm/kibana/index_pattern/install.ts b/x-pack/plugins/fleet/server/services/epm/kibana/index_pattern/install.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/kibana/index_pattern/install.ts rename to x-pack/plugins/fleet/server/services/epm/kibana/index_pattern/install.ts diff --git a/x-pack/plugins/ingest_manager/server/services/epm/kibana/index_pattern/tests/coredns.logs.yml b/x-pack/plugins/fleet/server/services/epm/kibana/index_pattern/tests/coredns.logs.yml similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/kibana/index_pattern/tests/coredns.logs.yml rename to x-pack/plugins/fleet/server/services/epm/kibana/index_pattern/tests/coredns.logs.yml diff --git a/x-pack/plugins/ingest_manager/server/services/epm/kibana/index_pattern/tests/nginx.access.ecs.yml b/x-pack/plugins/fleet/server/services/epm/kibana/index_pattern/tests/nginx.access.ecs.yml similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/kibana/index_pattern/tests/nginx.access.ecs.yml rename to x-pack/plugins/fleet/server/services/epm/kibana/index_pattern/tests/nginx.access.ecs.yml diff --git a/x-pack/plugins/ingest_manager/server/services/epm/kibana/index_pattern/tests/nginx.error.ecs.yml b/x-pack/plugins/fleet/server/services/epm/kibana/index_pattern/tests/nginx.error.ecs.yml similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/kibana/index_pattern/tests/nginx.error.ecs.yml rename to x-pack/plugins/fleet/server/services/epm/kibana/index_pattern/tests/nginx.error.ecs.yml diff --git a/x-pack/plugins/ingest_manager/server/services/epm/kibana/index_pattern/tests/nginx.fields.yml b/x-pack/plugins/fleet/server/services/epm/kibana/index_pattern/tests/nginx.fields.yml similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/kibana/index_pattern/tests/nginx.fields.yml rename to x-pack/plugins/fleet/server/services/epm/kibana/index_pattern/tests/nginx.fields.yml diff --git a/x-pack/plugins/ingest_manager/server/services/epm/kibana/index_pattern/tests/test_data.ts b/x-pack/plugins/fleet/server/services/epm/kibana/index_pattern/tests/test_data.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/kibana/index_pattern/tests/test_data.ts rename to x-pack/plugins/fleet/server/services/epm/kibana/index_pattern/tests/test_data.ts diff --git a/x-pack/plugins/ingest_manager/server/services/epm/packages/_install_package.test.ts b/x-pack/plugins/fleet/server/services/epm/packages/_install_package.test.ts similarity index 97% rename from x-pack/plugins/ingest_manager/server/services/epm/packages/_install_package.test.ts rename to x-pack/plugins/fleet/server/services/epm/packages/_install_package.test.ts index 5d3e8e9ce87d1..b7650d10b6b25 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/packages/_install_package.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/_install_package.test.ts @@ -61,11 +61,7 @@ describe('_installPackage', () => { const installationPromise = _installPackage({ savedObjectsClient: soClient, callCluster, - pkgName: 'abc', - pkgVersion: '1.2.3', paths: [], - removable: false, - internal: false, packageInfo: { name: 'xyz', version: '4.5.6', diff --git a/x-pack/plugins/ingest_manager/server/services/epm/packages/_install_package.ts b/x-pack/plugins/fleet/server/services/epm/packages/_install_package.ts similarity index 97% rename from x-pack/plugins/ingest_manager/server/services/epm/packages/_install_package.ts rename to x-pack/plugins/fleet/server/services/epm/packages/_install_package.ts index f570984cc61aa..a83d9428b7c93 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/packages/_install_package.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/_install_package.ts @@ -21,6 +21,7 @@ import { installPipelines, deletePreviousPipelines } from '../elasticsearch/inge import { installILMPolicy } from '../elasticsearch/ilm/install'; import { installKibanaAssets, getKibanaAssets } from '../kibana/assets/install'; import { updateCurrentWriteIndices } from '../elasticsearch/template/template'; +import { isRequiredPackage } from './index'; import { deleteKibanaSavedObjectsAssets } from './remove'; import { installTransform } from '../elasticsearch/transform/install'; import { createInstallation, saveKibanaAssetsRefs, updateVersion } from './install'; @@ -32,28 +33,22 @@ import { createInstallation, saveKibanaAssetsRefs, updateVersion } from './insta export async function _installPackage({ savedObjectsClient, callCluster, - pkgName, - pkgVersion, installedPkg, paths, - removable, - internal, packageInfo, installType, installSource, }: { savedObjectsClient: SavedObjectsClientContract; callCluster: CallESAsCurrentUser; - pkgName: string; - pkgVersion: string; installedPkg?: SavedObject; paths: string[]; - removable: boolean; - internal: boolean; packageInfo: InstallablePackage; installType: InstallType; installSource: InstallSource; }): Promise { + const { internal = false, name: pkgName, version: pkgVersion } = packageInfo; + const removable = !isRequiredPackage(pkgName); const toSaveESIndexPatterns = generateESIndexPatterns(packageInfo.data_streams); // add the package installation to the saved object. // if some installation already exists, just update install info diff --git a/x-pack/plugins/ingest_manager/server/services/epm/packages/assets.test.ts b/x-pack/plugins/fleet/server/services/epm/packages/assets.test.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/packages/assets.test.ts rename to x-pack/plugins/fleet/server/services/epm/packages/assets.test.ts diff --git a/x-pack/plugins/ingest_manager/server/services/epm/packages/assets.ts b/x-pack/plugins/fleet/server/services/epm/packages/assets.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/packages/assets.ts rename to x-pack/plugins/fleet/server/services/epm/packages/assets.ts diff --git a/x-pack/plugins/ingest_manager/server/services/epm/packages/bulk_install_packages.ts b/x-pack/plugins/fleet/server/services/epm/packages/bulk_install_packages.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/packages/bulk_install_packages.ts rename to x-pack/plugins/fleet/server/services/epm/packages/bulk_install_packages.ts diff --git a/x-pack/plugins/ingest_manager/server/services/epm/packages/ensure_installed_default_packages.test.ts b/x-pack/plugins/fleet/server/services/epm/packages/ensure_installed_default_packages.test.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/packages/ensure_installed_default_packages.test.ts rename to x-pack/plugins/fleet/server/services/epm/packages/ensure_installed_default_packages.test.ts diff --git a/x-pack/plugins/ingest_manager/server/services/epm/packages/get.ts b/x-pack/plugins/fleet/server/services/epm/packages/get.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/packages/get.ts rename to x-pack/plugins/fleet/server/services/epm/packages/get.ts diff --git a/x-pack/plugins/ingest_manager/server/services/epm/packages/get_install_type.test.ts b/x-pack/plugins/fleet/server/services/epm/packages/get_install_type.test.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/packages/get_install_type.test.ts rename to x-pack/plugins/fleet/server/services/epm/packages/get_install_type.test.ts diff --git a/x-pack/plugins/ingest_manager/server/services/epm/packages/index.ts b/x-pack/plugins/fleet/server/services/epm/packages/index.ts similarity index 96% rename from x-pack/plugins/ingest_manager/server/services/epm/packages/index.ts rename to x-pack/plugins/fleet/server/services/epm/packages/index.ts index 410a9c0b22537..a1128011d81e6 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/packages/index.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/index.ts @@ -29,8 +29,7 @@ export { BulkInstallResponse, IBulkInstallPackageError, handleInstallPackageFailure, - installPackageFromRegistry, - installPackageByUpload, + installPackage, ensureInstalledPackage, } from './install'; export { removeInstallation } from './remove'; diff --git a/x-pack/plugins/ingest_manager/server/services/epm/packages/install.ts b/x-pack/plugins/fleet/server/services/epm/packages/install.ts similarity index 88% rename from x-pack/plugins/ingest_manager/server/services/epm/packages/install.ts rename to x-pack/plugins/fleet/server/services/epm/packages/install.ts index e7d8c8d4695d4..00a5c689e906d 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/packages/install.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/install.ts @@ -24,7 +24,6 @@ import * as Registry from '../registry'; import { getInstallation, getInstallationObject, - isRequiredPackage, bulkInstallPackages, isBulkInstallError, } from './index'; @@ -52,7 +51,7 @@ export async function installLatestPackage(options: { name: latestPackage.name, version: latestPackage.version, }); - return installPackageFromRegistry({ savedObjectsClient, pkgkey, callCluster }); + return installPackage({ installSource: 'registry', savedObjectsClient, pkgkey, callCluster }); } catch (err) { throw err; } @@ -148,7 +147,8 @@ export async function handleInstallPackageFailure({ } const prevVersion = `${pkgName}-${installedPkg.attributes.version}`; logger.error(`rolling back to ${prevVersion} after error installing ${pkgkey}`); - await installPackageFromRegistry({ + await installPackage({ + installSource: 'registry', savedObjectsClient, pkgkey: prevVersion, callCluster, @@ -186,7 +186,12 @@ export async function upgradePackage({ }); try { - const assets = await installPackageFromRegistry({ savedObjectsClient, pkgkey, callCluster }); + const assets = await installPackage({ + installSource: 'registry', + savedObjectsClient, + pkgkey, + callCluster, + }); return { name: pkgToUpgrade, newVersion: latestPkg.version, @@ -218,19 +223,19 @@ export async function upgradePackage({ } } -interface InstallPackageParams { +interface InstallRegistryPackageParams { savedObjectsClient: SavedObjectsClientContract; pkgkey: string; callCluster: CallESAsCurrentUser; force?: boolean; } -export async function installPackageFromRegistry({ +async function installPackageFromRegistry({ savedObjectsClient, pkgkey, callCluster, force = false, -}: InstallPackageParams): Promise { +}: InstallRegistryPackageParams): Promise { // TODO: change epm API to /packageName/version so we don't need to do this const { pkgName, pkgVersion } = Registry.splitPkgKey(pkgkey); // TODO: calls to getInstallationObject, Registry.fetchInfo, and Registry.fetchFindLatestPackge @@ -250,37 +255,36 @@ export async function installPackageFromRegistry({ const { paths, registryPackageInfo } = await Registry.getRegistryPackage(pkgName, pkgVersion); - const removable = !isRequiredPackage(pkgName); - const { internal = false } = registryPackageInfo; - const installSource = 'registry'; - return _installPackage({ savedObjectsClient, callCluster, - pkgName, - pkgVersion, installedPkg, paths, - removable, - internal, packageInfo: registryPackageInfo, installType, - installSource, + installSource: 'registry', }); } -export async function installPackageByUpload({ - savedObjectsClient, - callCluster, - archiveBuffer, - contentType, -}: { +interface InstallUploadedArchiveParams { savedObjectsClient: SavedObjectsClientContract; callCluster: CallESAsCurrentUser; archiveBuffer: Buffer; contentType: string; -}): Promise { +} + +export type InstallPackageParams = + | ({ installSource: Extract } & InstallRegistryPackageParams) + | ({ installSource: Extract } & InstallUploadedArchiveParams); + +async function installPackageByUpload({ + savedObjectsClient, + callCluster, + archiveBuffer, + contentType, +}: InstallUploadedArchiveParams): Promise { const { paths, archivePackageInfo } = await loadArchivePackage({ archiveBuffer, contentType }); + const installedPkg = await getInstallationObject({ savedObjectsClient, pkgName: archivePackageInfo.name, @@ -292,25 +296,45 @@ export async function installPackageByUpload({ ); } - const removable = !isRequiredPackage(archivePackageInfo.name); - const { internal = false } = archivePackageInfo; - const installSource = 'upload'; - return _installPackage({ savedObjectsClient, callCluster, - pkgName: archivePackageInfo.name, - pkgVersion: archivePackageInfo.version, installedPkg, paths, - removable, - internal, packageInfo: archivePackageInfo, installType, - installSource, + installSource: 'upload', }); } +export async function installPackage(args: InstallPackageParams) { + if (!('installSource' in args)) { + throw new Error('installSource is required'); + } + + if (args.installSource === 'registry') { + const { savedObjectsClient, pkgkey, callCluster, force } = args; + + return installPackageFromRegistry({ + savedObjectsClient, + pkgkey, + callCluster, + force, + }); + } else if (args.installSource === 'upload') { + const { savedObjectsClient, callCluster, archiveBuffer, contentType } = args; + + return installPackageByUpload({ + savedObjectsClient, + callCluster, + archiveBuffer, + contentType, + }); + } + // @ts-expect-error s/b impossibe b/c `never` by this point, but just in case + throw new Error(`Unknown installSource: ${args.installSource}`); +} + export const updateVersion = async ( savedObjectsClient: SavedObjectsClientContract, pkgName: string, @@ -421,7 +445,9 @@ export async function ensurePackagesCompletedInstall( const pkgkey = `${pkg.attributes.name}-${pkg.attributes.install_version}`; // reinstall package if (elapsedTime > MAX_TIME_COMPLETE_INSTALL) { - acc.push(installPackageFromRegistry({ savedObjectsClient, pkgkey, callCluster })); + acc.push( + installPackage({ installSource: 'registry', savedObjectsClient, pkgkey, callCluster }) + ); } return acc; }, []); diff --git a/x-pack/plugins/ingest_manager/server/services/epm/packages/remove.ts b/x-pack/plugins/fleet/server/services/epm/packages/remove.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/packages/remove.ts rename to x-pack/plugins/fleet/server/services/epm/packages/remove.ts diff --git a/x-pack/plugins/ingest_manager/server/services/epm/registry/extract.ts b/x-pack/plugins/fleet/server/services/epm/registry/extract.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/registry/extract.ts rename to x-pack/plugins/fleet/server/services/epm/registry/extract.ts diff --git a/x-pack/plugins/ingest_manager/server/services/epm/registry/index.test.ts b/x-pack/plugins/fleet/server/services/epm/registry/index.test.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/registry/index.test.ts rename to x-pack/plugins/fleet/server/services/epm/registry/index.test.ts diff --git a/x-pack/plugins/ingest_manager/server/services/epm/registry/index.ts b/x-pack/plugins/fleet/server/services/epm/registry/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/registry/index.ts rename to x-pack/plugins/fleet/server/services/epm/registry/index.ts diff --git a/x-pack/plugins/ingest_manager/server/services/epm/registry/proxy.test.ts b/x-pack/plugins/fleet/server/services/epm/registry/proxy.test.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/registry/proxy.test.ts rename to x-pack/plugins/fleet/server/services/epm/registry/proxy.test.ts diff --git a/x-pack/plugins/ingest_manager/server/services/epm/registry/proxy.ts b/x-pack/plugins/fleet/server/services/epm/registry/proxy.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/registry/proxy.ts rename to x-pack/plugins/fleet/server/services/epm/registry/proxy.ts diff --git a/x-pack/plugins/ingest_manager/server/services/epm/registry/registry_url.ts b/x-pack/plugins/fleet/server/services/epm/registry/registry_url.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/registry/registry_url.ts rename to x-pack/plugins/fleet/server/services/epm/registry/registry_url.ts diff --git a/x-pack/plugins/ingest_manager/server/services/epm/registry/requests.test.ts b/x-pack/plugins/fleet/server/services/epm/registry/requests.test.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/registry/requests.test.ts rename to x-pack/plugins/fleet/server/services/epm/registry/requests.test.ts diff --git a/x-pack/plugins/ingest_manager/server/services/epm/registry/requests.ts b/x-pack/plugins/fleet/server/services/epm/registry/requests.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/registry/requests.ts rename to x-pack/plugins/fleet/server/services/epm/registry/requests.ts diff --git a/x-pack/plugins/ingest_manager/server/services/epm/registry/streams.ts b/x-pack/plugins/fleet/server/services/epm/registry/streams.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/epm/registry/streams.ts rename to x-pack/plugins/fleet/server/services/epm/registry/streams.ts diff --git a/x-pack/plugins/ingest_manager/server/services/es_index_pattern.ts b/x-pack/plugins/fleet/server/services/es_index_pattern.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/es_index_pattern.ts rename to x-pack/plugins/fleet/server/services/es_index_pattern.ts diff --git a/x-pack/plugins/ingest_manager/server/services/index.ts b/x-pack/plugins/fleet/server/services/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/index.ts rename to x-pack/plugins/fleet/server/services/index.ts diff --git a/x-pack/plugins/ingest_manager/server/services/install_script/index.ts b/x-pack/plugins/fleet/server/services/install_script/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/install_script/index.ts rename to x-pack/plugins/fleet/server/services/install_script/index.ts diff --git a/x-pack/plugins/ingest_manager/server/services/install_script/install_templates/linux.ts b/x-pack/plugins/fleet/server/services/install_script/install_templates/linux.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/install_script/install_templates/linux.ts rename to x-pack/plugins/fleet/server/services/install_script/install_templates/linux.ts diff --git a/x-pack/plugins/ingest_manager/server/services/install_script/install_templates/macos.ts b/x-pack/plugins/fleet/server/services/install_script/install_templates/macos.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/install_script/install_templates/macos.ts rename to x-pack/plugins/fleet/server/services/install_script/install_templates/macos.ts diff --git a/x-pack/plugins/ingest_manager/server/services/install_script/install_templates/types.ts b/x-pack/plugins/fleet/server/services/install_script/install_templates/types.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/install_script/install_templates/types.ts rename to x-pack/plugins/fleet/server/services/install_script/install_templates/types.ts diff --git a/x-pack/plugins/ingest_manager/server/services/license.ts b/x-pack/plugins/fleet/server/services/license.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/license.ts rename to x-pack/plugins/fleet/server/services/license.ts diff --git a/x-pack/plugins/ingest_manager/server/services/output.ts b/x-pack/plugins/fleet/server/services/output.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/output.ts rename to x-pack/plugins/fleet/server/services/output.ts diff --git a/x-pack/plugins/ingest_manager/server/services/package_policy.test.ts b/x-pack/plugins/fleet/server/services/package_policy.test.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/package_policy.test.ts rename to x-pack/plugins/fleet/server/services/package_policy.test.ts diff --git a/x-pack/plugins/ingest_manager/server/services/package_policy.ts b/x-pack/plugins/fleet/server/services/package_policy.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/package_policy.ts rename to x-pack/plugins/fleet/server/services/package_policy.ts diff --git a/x-pack/plugins/ingest_manager/server/services/saved_object.test.ts b/x-pack/plugins/fleet/server/services/saved_object.test.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/saved_object.test.ts rename to x-pack/plugins/fleet/server/services/saved_object.test.ts diff --git a/x-pack/plugins/ingest_manager/server/services/saved_object.ts b/x-pack/plugins/fleet/server/services/saved_object.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/saved_object.ts rename to x-pack/plugins/fleet/server/services/saved_object.ts diff --git a/x-pack/plugins/ingest_manager/server/services/settings.ts b/x-pack/plugins/fleet/server/services/settings.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/settings.ts rename to x-pack/plugins/fleet/server/services/settings.ts diff --git a/x-pack/plugins/ingest_manager/server/services/setup.test.ts b/x-pack/plugins/fleet/server/services/setup.test.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/setup.test.ts rename to x-pack/plugins/fleet/server/services/setup.test.ts diff --git a/x-pack/plugins/ingest_manager/server/services/setup.ts b/x-pack/plugins/fleet/server/services/setup.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/setup.ts rename to x-pack/plugins/fleet/server/services/setup.ts diff --git a/x-pack/plugins/ingest_manager/server/services/setup_utils.test.ts b/x-pack/plugins/fleet/server/services/setup_utils.test.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/setup_utils.test.ts rename to x-pack/plugins/fleet/server/services/setup_utils.test.ts diff --git a/x-pack/plugins/ingest_manager/server/services/setup_utils.ts b/x-pack/plugins/fleet/server/services/setup_utils.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/services/setup_utils.ts rename to x-pack/plugins/fleet/server/services/setup_utils.ts diff --git a/x-pack/plugins/ingest_manager/server/types/index.tsx b/x-pack/plugins/fleet/server/types/index.tsx similarity index 100% rename from x-pack/plugins/ingest_manager/server/types/index.tsx rename to x-pack/plugins/fleet/server/types/index.tsx diff --git a/x-pack/plugins/ingest_manager/server/types/models/agent.ts b/x-pack/plugins/fleet/server/types/models/agent.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/types/models/agent.ts rename to x-pack/plugins/fleet/server/types/models/agent.ts diff --git a/x-pack/plugins/ingest_manager/server/types/models/agent_policy.ts b/x-pack/plugins/fleet/server/types/models/agent_policy.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/types/models/agent_policy.ts rename to x-pack/plugins/fleet/server/types/models/agent_policy.ts diff --git a/x-pack/plugins/ingest_manager/server/types/models/enrollment_api_key.ts b/x-pack/plugins/fleet/server/types/models/enrollment_api_key.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/types/models/enrollment_api_key.ts rename to x-pack/plugins/fleet/server/types/models/enrollment_api_key.ts diff --git a/x-pack/plugins/ingest_manager/server/types/models/index.ts b/x-pack/plugins/fleet/server/types/models/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/types/models/index.ts rename to x-pack/plugins/fleet/server/types/models/index.ts diff --git a/x-pack/plugins/ingest_manager/server/types/models/output.ts b/x-pack/plugins/fleet/server/types/models/output.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/types/models/output.ts rename to x-pack/plugins/fleet/server/types/models/output.ts diff --git a/x-pack/plugins/ingest_manager/server/types/models/package_policy.ts b/x-pack/plugins/fleet/server/types/models/package_policy.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/types/models/package_policy.ts rename to x-pack/plugins/fleet/server/types/models/package_policy.ts diff --git a/x-pack/plugins/ingest_manager/server/types/rest_spec/agent.ts b/x-pack/plugins/fleet/server/types/rest_spec/agent.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/types/rest_spec/agent.ts rename to x-pack/plugins/fleet/server/types/rest_spec/agent.ts diff --git a/x-pack/plugins/ingest_manager/server/types/rest_spec/agent_policy.ts b/x-pack/plugins/fleet/server/types/rest_spec/agent_policy.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/types/rest_spec/agent_policy.ts rename to x-pack/plugins/fleet/server/types/rest_spec/agent_policy.ts diff --git a/x-pack/plugins/ingest_manager/server/types/rest_spec/common.ts b/x-pack/plugins/fleet/server/types/rest_spec/common.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/types/rest_spec/common.ts rename to x-pack/plugins/fleet/server/types/rest_spec/common.ts diff --git a/x-pack/plugins/ingest_manager/server/types/rest_spec/enrollment_api_key.ts b/x-pack/plugins/fleet/server/types/rest_spec/enrollment_api_key.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/types/rest_spec/enrollment_api_key.ts rename to x-pack/plugins/fleet/server/types/rest_spec/enrollment_api_key.ts diff --git a/x-pack/plugins/ingest_manager/server/types/rest_spec/epm.ts b/x-pack/plugins/fleet/server/types/rest_spec/epm.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/types/rest_spec/epm.ts rename to x-pack/plugins/fleet/server/types/rest_spec/epm.ts diff --git a/x-pack/plugins/ingest_manager/server/types/rest_spec/index.ts b/x-pack/plugins/fleet/server/types/rest_spec/index.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/types/rest_spec/index.ts rename to x-pack/plugins/fleet/server/types/rest_spec/index.ts diff --git a/x-pack/plugins/ingest_manager/server/types/rest_spec/install_script.ts b/x-pack/plugins/fleet/server/types/rest_spec/install_script.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/types/rest_spec/install_script.ts rename to x-pack/plugins/fleet/server/types/rest_spec/install_script.ts diff --git a/x-pack/plugins/ingest_manager/server/types/rest_spec/output.ts b/x-pack/plugins/fleet/server/types/rest_spec/output.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/types/rest_spec/output.ts rename to x-pack/plugins/fleet/server/types/rest_spec/output.ts diff --git a/x-pack/plugins/ingest_manager/server/types/rest_spec/package_policy.ts b/x-pack/plugins/fleet/server/types/rest_spec/package_policy.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/types/rest_spec/package_policy.ts rename to x-pack/plugins/fleet/server/types/rest_spec/package_policy.ts diff --git a/x-pack/plugins/ingest_manager/server/types/rest_spec/settings.ts b/x-pack/plugins/fleet/server/types/rest_spec/settings.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/types/rest_spec/settings.ts rename to x-pack/plugins/fleet/server/types/rest_spec/settings.ts diff --git a/x-pack/plugins/ingest_manager/server/types/rest_spec/setup.ts b/x-pack/plugins/fleet/server/types/rest_spec/setup.ts similarity index 100% rename from x-pack/plugins/ingest_manager/server/types/rest_spec/setup.ts rename to x-pack/plugins/fleet/server/types/rest_spec/setup.ts diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/app/app.helpers.tsx b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/app/app.helpers.tsx new file mode 100644 index 0000000000000..de7242a6c5ddf --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/app/app.helpers.tsx @@ -0,0 +1,74 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { act } from 'react-dom/test-utils'; +import { registerTestBed, TestBed, TestBedConfig } from '../../../../../test_utils'; +import { App } from '../../../public/application/app'; +import { TestSubjects } from '../helpers'; +import { createBreadcrumbsMock } from '../../../public/application/services/breadcrumbs.mock'; +import { KibanaContextProvider } from '../../../../../../src/plugins/kibana_react/public/context'; + +const breadcrumbService = createBreadcrumbsMock(); + +const AppWithContext = (props: any) => { + return ( + + + + ); +}; + +const getTestBedConfig = (initialEntries: string[]): TestBedConfig => ({ + memoryRouter: { + initialEntries, + }, + defaultProps: { + getUrlForApp: () => {}, + navigateToApp: () => {}, + }, +}); + +const initTestBed = (initialEntries: string[]) => + registerTestBed(AppWithContext, getTestBedConfig(initialEntries))(); + +export interface AppTestBed extends TestBed { + actions: { + clickPolicyNameLink: () => void; + clickCreatePolicyButton: () => void; + }; +} + +export const setup = async (initialEntries: string[]): Promise => { + const testBed = await initTestBed(initialEntries); + + const clickPolicyNameLink = async () => { + const { component, find } = testBed; + await act(async () => { + find('policyTablePolicyNameLink').simulate('click', { button: 0 }); + }); + component.update(); + }; + + const clickCreatePolicyButton = async () => { + const { component, find } = testBed; + await act(async () => { + find('createPolicyButton').simulate('click', { button: 0 }); + }); + component.update(); + }; + + return { + ...testBed, + actions: { clickPolicyNameLink, clickCreatePolicyButton }, + }; +}; + +export const getEncodedPolicyEditPath = (policyName: string): string => + `/policies/edit/${encodeURIComponent(policyName)}`; + +export const getDoubleEncodedPolicyEditPath = (policyName: string): string => + encodeURI(getEncodedPolicyEditPath(policyName)); diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/app/app.test.ts b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/app/app.test.ts new file mode 100644 index 0000000000000..9052cf2847baa --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/app/app.test.ts @@ -0,0 +1,252 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { + AppTestBed, + getDoubleEncodedPolicyEditPath, + getEncodedPolicyEditPath, + setup, +} from './app.helpers'; +import { setupEnvironment } from '../helpers/setup_environment'; +import { getDefaultHotPhasePolicy, POLICY_NAME } from '../edit_policy/constants'; +import { act } from 'react-dom/test-utils'; + +const SPECIAL_CHARS_NAME = 'test?#$+=&@:'; +const PERCENT_SIGN_NAME = 'test%'; +// navigation doesn't work for % with other special chars or sequence %25 +// known issue https://github.com/elastic/kibana/issues/82440 +const PERCENT_SIGN_WITH_OTHER_CHARS_NAME = 'test%#'; +const PERCENT_SIGN_25_SEQUENCE = 'test%25'; + +window.scrollTo = jest.fn(); + +describe('', () => { + let testBed: AppTestBed; + const { server, httpRequestsMockHelpers } = setupEnvironment(); + afterAll(() => { + server.restore(); + }); + + describe('new policy creation', () => { + test('when there are no policies', async () => { + httpRequestsMockHelpers.setLoadPolicies([]); + await act(async () => { + testBed = await setup(['/']); + }); + + const { component, actions } = testBed; + component.update(); + + await actions.clickCreatePolicyButton(); + component.update(); + + expect(testBed.find('policyTitle').text()).toBe(`Create an index lifecycle policy`); + expect(testBed.find('policyNameField').props().value).toBe(''); + }); + + test('when there are policies', async () => { + httpRequestsMockHelpers.setLoadPolicies([getDefaultHotPhasePolicy(POLICY_NAME)]); + await act(async () => { + testBed = await setup(['/']); + }); + + const { component, actions } = testBed; + component.update(); + + await actions.clickCreatePolicyButton(); + component.update(); + + expect(testBed.find('policyTitle').text()).toBe(`Create an index lifecycle policy`); + expect(testBed.find('policyNameField').props().value).toBe(''); + }); + }); + + describe('navigation with special characters', () => { + beforeAll(async () => { + httpRequestsMockHelpers.setLoadPolicies([getDefaultHotPhasePolicy(SPECIAL_CHARS_NAME)]); + }); + + test('clicking policy name in the table works', async () => { + await act(async () => { + testBed = await setup(['/']); + }); + + const { component, actions } = testBed; + component.update(); + + await actions.clickPolicyNameLink(); + component.update(); + + expect(testBed.find('policyTitle').text()).toBe( + `Edit index lifecycle policy ${SPECIAL_CHARS_NAME}` + ); + }); + + test('loading edit policy page url works', async () => { + await act(async () => { + testBed = await setup([getEncodedPolicyEditPath(SPECIAL_CHARS_NAME)]); + }); + + const { component } = testBed; + component.update(); + + expect(testBed.find('policyTitle').text()).toBe( + `Edit index lifecycle policy ${SPECIAL_CHARS_NAME}` + ); + }); + + // using double encoding to counteract react-router's v5 internal decodeURI call + // when those links are open in a new tab, address bar contains double encoded url + test('loading edit policy page url with double encoding works', async () => { + await act(async () => { + testBed = await setup([getDoubleEncodedPolicyEditPath(SPECIAL_CHARS_NAME)]); + }); + + const { component } = testBed; + component.update(); + + expect(testBed.find('policyTitle').text()).toBe( + `Edit index lifecycle policy ${SPECIAL_CHARS_NAME}` + ); + }); + }); + + describe('navigation with percent sign', () => { + beforeAll(async () => { + httpRequestsMockHelpers.setLoadPolicies([getDefaultHotPhasePolicy(PERCENT_SIGN_NAME)]); + }); + + test('loading edit policy page url works', async () => { + await act(async () => { + testBed = await setup([getEncodedPolicyEditPath(PERCENT_SIGN_NAME)]); + }); + + const { component } = testBed; + component.update(); + + expect(testBed.find('policyTitle').text()).toBe( + `Edit index lifecycle policy ${PERCENT_SIGN_NAME}` + ); + }); + + test('loading edit policy page url with double encoding works', async () => { + await act(async () => { + testBed = await setup([getDoubleEncodedPolicyEditPath(PERCENT_SIGN_NAME)]); + }); + + const { component } = testBed; + component.update(); + + expect(testBed.find('policyTitle').text()).toBe( + `Edit index lifecycle policy ${PERCENT_SIGN_NAME}` + ); + }); + }); + + describe('navigation with percent sign with other special characters', () => { + beforeAll(async () => { + httpRequestsMockHelpers.setLoadPolicies([ + getDefaultHotPhasePolicy(PERCENT_SIGN_WITH_OTHER_CHARS_NAME), + ]); + }); + + test('clicking policy name in the table works', async () => { + await act(async () => { + testBed = await setup(['/']); + }); + + const { component, actions } = testBed; + component.update(); + + await actions.clickPolicyNameLink(); + component.update(); + + expect(testBed.find('policyTitle').text()).toBe( + `Edit index lifecycle policy ${PERCENT_SIGN_WITH_OTHER_CHARS_NAME}` + ); + }); + + test("loading edit policy page url doesn't work", async () => { + await act(async () => { + testBed = await setup([getEncodedPolicyEditPath(PERCENT_SIGN_WITH_OTHER_CHARS_NAME)]); + }); + + const { component } = testBed; + component.update(); + + // known issue https://github.com/elastic/kibana/issues/82440 + expect(testBed.find('policyTitle').text()).not.toBe( + `Edit index lifecycle policy ${PERCENT_SIGN_WITH_OTHER_CHARS_NAME}` + ); + }); + + // using double encoding to counteract react-router's v5 internal decodeURI call + // when those links are open in a new tab, address bar contains double encoded url + test('loading edit policy page url with double encoding works', async () => { + await act(async () => { + testBed = await setup([getDoubleEncodedPolicyEditPath(PERCENT_SIGN_WITH_OTHER_CHARS_NAME)]); + }); + + const { component } = testBed; + component.update(); + + expect(testBed.find('policyTitle').text()).toBe( + `Edit index lifecycle policy ${PERCENT_SIGN_WITH_OTHER_CHARS_NAME}` + ); + }); + }); + + describe('navigation with %25 sequence', () => { + beforeAll(async () => { + httpRequestsMockHelpers.setLoadPolicies([getDefaultHotPhasePolicy(PERCENT_SIGN_25_SEQUENCE)]); + }); + + test('clicking policy name in the table works correctly', async () => { + await act(async () => { + testBed = await setup(['/']); + }); + + const { component, actions } = testBed; + component.update(); + + await actions.clickPolicyNameLink(); + component.update(); + + expect(testBed.find('policyTitle').text()).toBe( + `Edit index lifecycle policy ${PERCENT_SIGN_25_SEQUENCE}` + ); + }); + + test("loading edit policy page url doesn't work", async () => { + await act(async () => { + testBed = await setup([getEncodedPolicyEditPath(PERCENT_SIGN_25_SEQUENCE)]); + }); + + const { component } = testBed; + component.update(); + + // known issue https://github.com/elastic/kibana/issues/82440 + expect(testBed.find('policyTitle').text()).not.toBe( + `Edit index lifecycle policy ${PERCENT_SIGN_25_SEQUENCE}` + ); + }); + + // using double encoding to counteract react-router's v5 internal decodeURI call + // when those links are open in a new tab, address bar contains double encoded url + test('loading edit policy page url with double encoding works', async () => { + await act(async () => { + testBed = await setup([getDoubleEncodedPolicyEditPath(PERCENT_SIGN_25_SEQUENCE)]); + }); + + const { component } = testBed; + component.update(); + + expect(testBed.find('policyTitle').text()).toBe( + `Edit index lifecycle policy ${PERCENT_SIGN_25_SEQUENCE}` + ); + }); + }); +}); diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/constants.ts b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/constants.ts index 3d430cf31621e..00c7d705c1f44 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/constants.ts +++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/constants.ts @@ -121,6 +121,26 @@ export const DELETE_PHASE_POLICY: PolicyFromES = { name: POLICY_NAME, }; +export const getDefaultHotPhasePolicy = (policyName: string): PolicyFromES => ({ + version: 1, + modified_date: Date.now().toString(), + policy: { + name: policyName, + phases: { + hot: { + min_age: '0ms', + actions: { + rollover: { + max_age: '30d', + max_size: '50gb', + }, + }, + }, + }, + }, + name: policyName, +}); + export const POLICY_WITH_NODE_ATTR_AND_OFF_ALLOCATION: PolicyFromES = { version: 1, modified_date: Date.now().toString(), diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.helpers.tsx b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.helpers.tsx index 0b9f47e188d15..646978dd68153 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.helpers.tsx +++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.helpers.tsx @@ -221,6 +221,11 @@ export const setup = async () => { setFreeze, setIndexPriority: setIndexPriority('cold'), }, + delete: { + enable: enable('delete'), + setMinAgeValue: setMinAgeValue('delete'), + setMinAgeUnits: setMinAgeUnits('delete'), + }, }, }; }; diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.test.ts b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.test.ts index 11fadf51f27f8..c91ee3e2a1c06 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.test.ts +++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.test.ts @@ -19,6 +19,7 @@ import { POLICY_WITH_INCLUDE_EXCLUDE, POLICY_WITH_NODE_ATTR_AND_OFF_ALLOCATION, POLICY_WITH_NODE_ROLE_ALLOCATION, + getDefaultHotPhasePolicy, } from './constants'; window.scrollTo = jest.fn(); @@ -33,7 +34,7 @@ describe('', () => { describe('hot phase', () => { describe('serialization', () => { beforeEach(async () => { - httpRequestsMockHelpers.setLoadPolicies([DEFAULT_POLICY]); + httpRequestsMockHelpers.setLoadPolicies([getDefaultHotPhasePolicy('my_policy')]); httpRequestsMockHelpers.setLoadSnapshotPolicies([]); await act(async () => { @@ -367,7 +368,6 @@ describe('', () => { expect(testBed.find('snapshotPolicyCombobox').prop('data-currentvalue')).toEqual([ { label: DELETE_PHASE_POLICY.policy.phases.delete?.actions.wait_for_snapshot?.policy, - value: DELETE_PHASE_POLICY.policy.phases.delete?.actions.wait_for_snapshot?.policy, }, ]); }); @@ -412,7 +412,7 @@ describe('', () => { test('wait for snapshot field should delete action if field is empty', async () => { const { actions } = testBed; - actions.setWaitForSnapshotPolicy(''); + await actions.setWaitForSnapshotPolicy(''); await actions.savePolicy(); const expected = { diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/index.ts b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/index.ts index e8ebc2963d16a..aff9151da61f9 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/index.ts +++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/index.ts @@ -17,5 +17,8 @@ export type TestSubjects = | 'hot-selectedMaxDocuments' | 'hot-selectedMaxAge' | 'hot-selectedMaxAgeUnits' + | 'policyTablePolicyNameLink' + | 'policyTitle' + | 'createPolicyButton' | 'freezeSwitch' | string; diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/components/edit_policy.test.tsx b/x-pack/plugins/index_lifecycle_management/__jest__/components/edit_policy.test.tsx index 4a3fedfb264ac..43910583ceec9 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/components/edit_policy.test.tsx +++ b/x-pack/plugins/index_lifecycle_management/__jest__/components/edit_policy.test.tsx @@ -20,27 +20,27 @@ import { notificationServiceMock, fatalErrorsServiceMock, } from '../../../../../src/core/public/mocks'; + import { usageCollectionPluginMock } from '../../../../../src/plugins/usage_collection/public/mocks'; + import { CloudSetup } from '../../../cloud/public'; import { EditPolicy } from '../../public/application/sections/edit_policy/edit_policy'; +import { + EditPolicyContextProvider, + EditPolicyContextValue, +} from '../../public/application/sections/edit_policy/edit_policy_context'; + import { KibanaContextProvider } from '../../public/shared_imports'; + import { init as initHttp } from '../../public/application/services/http'; import { init as initUiMetric } from '../../public/application/services/ui_metric'; import { init as initNotification } from '../../public/application/services/notification'; import { PolicyFromES } from '../../common/types'; -import { - positiveNumberRequiredMessage, - policyNameRequiredMessage, - policyNameStartsWithUnderscoreErrorMessage, - policyNameContainsCommaErrorMessage, - policyNameContainsSpaceErrorMessage, - policyNameMustBeDifferentErrorMessage, - policyNameAlreadyUsedErrorMessage, -} from '../../public/application/services/policies/policy_validation'; import { i18nTexts } from '../../public/application/sections/edit_policy/i18n_texts'; import { editPolicyHelpers } from './helpers'; +import { defaultPolicy } from '../../public/application/constants'; // @ts-ignore initHttp(axios.create({ adapter: axiosXhrAdapter })); @@ -122,14 +122,11 @@ const noRollover = async (rendered: ReactWrapper) => { const getNodeAttributeSelect = (rendered: ReactWrapper, phase: string) => { return findTestSubject(rendered, `${phase}-selectedNodeAttrs`); }; -const setPolicyName = (rendered: ReactWrapper, policyName: string) => { +const setPolicyName = async (rendered: ReactWrapper, policyName: string) => { const policyNameField = findTestSubject(rendered, 'policyNameField'); - policyNameField.simulate('change', { target: { value: policyName } }); - rendered.update(); -}; -const setPhaseAfterLegacy = (rendered: ReactWrapper, phase: string, after: string | number) => { - const afterInput = rendered.find(`input#${phase}-selectedMinimumAge`); - afterInput.simulate('change', { target: { value: after } }); + await act(async () => { + policyNameField.simulate('change', { target: { value: policyName } }); + }); rendered.update(); }; const setPhaseAfter = async (rendered: ReactWrapper, phase: string, after: string | number) => { @@ -157,6 +154,32 @@ const save = async (rendered: ReactWrapper) => { }); rendered.update(); }; + +const MyComponent = ({ + isCloudEnabled, + isNewPolicy, + policy: _policy, + existingPolicies, + getUrlForApp, + policyName, +}: EditPolicyContextValue & { isCloudEnabled: boolean }) => { + return ( + + + + + + ); +}; + describe('edit policy', () => { beforeAll(() => { jest.useFakeTimers(); @@ -179,14 +202,14 @@ describe('edit policy', () => { beforeEach(() => { component = ( - - - + ); ({ http } = editPolicyHelpers.setup()); @@ -198,62 +221,78 @@ describe('edit policy', () => { test('should show error when trying to save empty form', async () => { const rendered = mountWithIntl(component); await save(rendered); - expectedErrorMessages(rendered, [policyNameRequiredMessage]); + expectedErrorMessages(rendered, [i18nTexts.editPolicy.errors.policyNameRequiredMessage]); }); test('should show error when trying to save policy name with space', async () => { const rendered = mountWithIntl(component); await noRollover(rendered); - setPolicyName(rendered, 'my policy'); - await save(rendered); - expectedErrorMessages(rendered, [policyNameContainsSpaceErrorMessage]); + await setPolicyName(rendered, 'my policy'); + waitForFormLibValidation(rendered); + expectedErrorMessages(rendered, [i18nTexts.editPolicy.errors.policyNameContainsInvalidChars]); }); test('should show error when trying to save policy name that is already used', async () => { const rendered = mountWithIntl(component); await noRollover(rendered); - setPolicyName(rendered, 'testy0'); - rendered.update(); - await save(rendered); - expectedErrorMessages(rendered, [policyNameAlreadyUsedErrorMessage]); + await setPolicyName(rendered, 'testy0'); + waitForFormLibValidation(rendered); + expectedErrorMessages(rendered, [ + i18nTexts.editPolicy.errors.policyNameAlreadyUsedErrorMessage, + ]); }); test('should show error when trying to save as new policy but using the same name', async () => { component = ( - ); const rendered = mountWithIntl(component); findTestSubject(rendered, 'saveAsNewSwitch').simulate('click'); rendered.update(); - setPolicyName(rendered, 'testy0'); - await save(rendered); - expectedErrorMessages(rendered, [policyNameMustBeDifferentErrorMessage]); + await setPolicyName(rendered, 'testy0'); + waitForFormLibValidation(rendered); + expectedErrorMessages(rendered, [ + i18nTexts.editPolicy.errors.policyNameAlreadyUsedErrorMessage, + ]); }); test('should show error when trying to save policy name with comma', async () => { const rendered = mountWithIntl(component); await noRollover(rendered); - setPolicyName(rendered, 'my,policy'); - await save(rendered); - expectedErrorMessages(rendered, [policyNameContainsCommaErrorMessage]); + await setPolicyName(rendered, 'my,policy'); + waitForFormLibValidation(rendered); + expectedErrorMessages(rendered, [i18nTexts.editPolicy.errors.policyNameContainsInvalidChars]); }); test('should show error when trying to save policy name starting with underscore', async () => { const rendered = mountWithIntl(component); await noRollover(rendered); - setPolicyName(rendered, '_mypolicy'); - await save(rendered); - expectedErrorMessages(rendered, [policyNameStartsWithUnderscoreErrorMessage]); + await setPolicyName(rendered, '_mypolicy'); + waitForFormLibValidation(rendered); + expectedErrorMessages(rendered, [ + i18nTexts.editPolicy.errors.policyNameStartsWithUnderscoreErrorMessage, + ]); }); test('should show correct json in policy flyout', async () => { - const rendered = mountWithIntl(component); + const rendered = mountWithIntl( + + ); await act(async () => { findTestSubject(rendered, 'requestButton').simulate('click'); }); rendered.update(); + const json = rendered.find(`code`).text(); - const expected = `PUT _ilm/policy/\n${JSON.stringify( + const expected = `PUT _ilm/policy/my-policy\n${JSON.stringify( { policy: { phases: { @@ -282,7 +321,7 @@ describe('edit policy', () => { test('should show errors when trying to save with no max size and no max age', async () => { const rendered = mountWithIntl(component); expect(findTestSubject(rendered, 'rolloverSettingsRequired').exists()).toBeFalsy(); - setPolicyName(rendered, 'mypolicy'); + await setPolicyName(rendered, 'mypolicy'); const maxSizeInput = findTestSubject(rendered, 'hot-selectedMaxSizeStored'); await act(async () => { maxSizeInput.simulate('change', { target: { value: '' } }); @@ -298,7 +337,7 @@ describe('edit policy', () => { }); test('should show number above 0 required error when trying to save with -1 for max size', async () => { const rendered = mountWithIntl(component); - setPolicyName(rendered, 'mypolicy'); + await setPolicyName(rendered, 'mypolicy'); const maxSizeInput = findTestSubject(rendered, 'hot-selectedMaxSizeStored'); await act(async () => { maxSizeInput.simulate('change', { target: { value: '-1' } }); @@ -309,7 +348,7 @@ describe('edit policy', () => { }); test('should show number above 0 required error when trying to save with 0 for max size', async () => { const rendered = mountWithIntl(component); - setPolicyName(rendered, 'mypolicy'); + await setPolicyName(rendered, 'mypolicy'); const maxSizeInput = findTestSubject(rendered, 'hot-selectedMaxSizeStored'); await act(async () => { maxSizeInput.simulate('change', { target: { value: '-1' } }); @@ -319,7 +358,7 @@ describe('edit policy', () => { }); test('should show number above 0 required error when trying to save with -1 for max age', async () => { const rendered = mountWithIntl(component); - setPolicyName(rendered, 'mypolicy'); + await setPolicyName(rendered, 'mypolicy'); const maxAgeInput = findTestSubject(rendered, 'hot-selectedMaxAge'); await act(async () => { maxAgeInput.simulate('change', { target: { value: '-1' } }); @@ -329,7 +368,7 @@ describe('edit policy', () => { }); test('should show number above 0 required error when trying to save with 0 for max age', async () => { const rendered = mountWithIntl(component); - setPolicyName(rendered, 'mypolicy'); + await setPolicyName(rendered, 'mypolicy'); const maxAgeInput = findTestSubject(rendered, 'hot-selectedMaxAge'); await act(async () => { maxAgeInput.simulate('change', { target: { value: '0' } }); @@ -337,21 +376,21 @@ describe('edit policy', () => { waitForFormLibValidation(rendered); expectedErrorMessages(rendered, [i18nTexts.editPolicy.errors.numberGreatThan0Required]); }); - test('should show forcemerge input when rollover enabled', () => { + test('should show forcemerge input when rollover enabled', async () => { const rendered = mountWithIntl(component); - setPolicyName(rendered, 'mypolicy'); + await setPolicyName(rendered, 'mypolicy'); expect(findTestSubject(rendered, 'hot-forceMergeSwitch').exists()).toBeTruthy(); }); test('should hide forcemerge input when rollover is disabled', async () => { const rendered = mountWithIntl(component); - setPolicyName(rendered, 'mypolicy'); + await setPolicyName(rendered, 'mypolicy'); await noRollover(rendered); waitForFormLibValidation(rendered); expect(findTestSubject(rendered, 'hot-forceMergeSwitch').exists()).toBeFalsy(); }); test('should show positive number required above zero error when trying to save hot phase with 0 for force merge', async () => { const rendered = mountWithIntl(component); - setPolicyName(rendered, 'mypolicy'); + await setPolicyName(rendered, 'mypolicy'); act(() => { findTestSubject(rendered, 'hot-forceMergeSwitch').simulate('click'); }); @@ -365,7 +404,7 @@ describe('edit policy', () => { }); test('should show positive number above 0 required error when trying to save hot phase with -1 for force merge', async () => { const rendered = mountWithIntl(component); - setPolicyName(rendered, 'mypolicy'); + await setPolicyName(rendered, 'mypolicy'); findTestSubject(rendered, 'hot-forceMergeSwitch').simulate('click'); rendered.update(); const forcemergeInput = findTestSubject(rendered, 'hot-selectedForceMergeSegments'); @@ -379,7 +418,7 @@ describe('edit policy', () => { test('should show positive number required error when trying to save with -1 for index priority', async () => { const rendered = mountWithIntl(component); await noRollover(rendered); - setPolicyName(rendered, 'mypolicy'); + await setPolicyName(rendered, 'mypolicy'); await setPhaseIndexPriority(rendered, 'hot', '-1'); waitForFormLibValidation(rendered); expectedErrorMessages(rendered, [i18nTexts.editPolicy.errors.nonNegativeNumberRequired]); @@ -397,7 +436,7 @@ describe('edit policy', () => { test('should show number required error when trying to save empty warm phase', async () => { const rendered = mountWithIntl(component); await noRollover(rendered); - setPolicyName(rendered, 'mypolicy'); + await setPolicyName(rendered, 'mypolicy'); await activatePhase(rendered, 'warm'); await setPhaseAfter(rendered, 'warm', ''); waitForFormLibValidation(rendered); @@ -406,7 +445,7 @@ describe('edit policy', () => { test('should allow 0 for phase timing', async () => { const rendered = mountWithIntl(component); await noRollover(rendered); - setPolicyName(rendered, 'mypolicy'); + await setPolicyName(rendered, 'mypolicy'); await activatePhase(rendered, 'warm'); await setPhaseAfter(rendered, 'warm', '0'); waitForFormLibValidation(rendered); @@ -415,7 +454,7 @@ describe('edit policy', () => { test('should show positive number required error when trying to save warm phase with -1 for after', async () => { const rendered = mountWithIntl(component); await noRollover(rendered); - setPolicyName(rendered, 'mypolicy'); + await setPolicyName(rendered, 'mypolicy'); await activatePhase(rendered, 'warm'); await setPhaseAfter(rendered, 'warm', '-1'); waitForFormLibValidation(rendered); @@ -424,7 +463,7 @@ describe('edit policy', () => { test('should show positive number required error when trying to save warm phase with -1 for index priority', async () => { const rendered = mountWithIntl(component); await noRollover(rendered); - setPolicyName(rendered, 'mypolicy'); + await setPolicyName(rendered, 'mypolicy'); await activatePhase(rendered, 'warm'); await setPhaseAfter(rendered, 'warm', '1'); await setPhaseAfter(rendered, 'warm', '-1'); @@ -434,7 +473,7 @@ describe('edit policy', () => { test('should show positive number required above zero error when trying to save warm phase with 0 for shrink', async () => { const rendered = mountWithIntl(component); await noRollover(rendered); - setPolicyName(rendered, 'mypolicy'); + await setPolicyName(rendered, 'mypolicy'); await activatePhase(rendered, 'warm'); act(() => { findTestSubject(rendered, 'shrinkSwitch').simulate('click'); @@ -451,7 +490,7 @@ describe('edit policy', () => { test('should show positive number above 0 required error when trying to save warm phase with -1 for shrink', async () => { const rendered = mountWithIntl(component); await noRollover(rendered); - setPolicyName(rendered, 'mypolicy'); + await setPolicyName(rendered, 'mypolicy'); await activatePhase(rendered, 'warm'); await setPhaseAfter(rendered, 'warm', '1'); act(() => { @@ -468,7 +507,7 @@ describe('edit policy', () => { test('should show positive number required above zero error when trying to save warm phase with 0 for force merge', async () => { const rendered = mountWithIntl(component); await noRollover(rendered); - setPolicyName(rendered, 'mypolicy'); + await setPolicyName(rendered, 'mypolicy'); await activatePhase(rendered, 'warm'); await setPhaseAfter(rendered, 'warm', '1'); act(() => { @@ -485,7 +524,7 @@ describe('edit policy', () => { test('should show positive number above 0 required error when trying to save warm phase with -1 for force merge', async () => { const rendered = mountWithIntl(component); await noRollover(rendered); - setPolicyName(rendered, 'mypolicy'); + await setPolicyName(rendered, 'mypolicy'); await activatePhase(rendered, 'warm'); await setPhaseAfter(rendered, 'warm', '1'); await act(async () => { @@ -503,7 +542,7 @@ describe('edit policy', () => { server.respondImmediately = false; const rendered = mountWithIntl(component); await noRollover(rendered); - setPolicyName(rendered, 'mypolicy'); + await setPolicyName(rendered, 'mypolicy'); await activatePhase(rendered, 'warm'); expect(rendered.find('.euiLoadingSpinner').exists()).toBeTruthy(); expect(rendered.find('.euiCallOut--warning').exists()).toBeFalsy(); @@ -517,7 +556,7 @@ describe('edit policy', () => { }); const rendered = mountWithIntl(component); await noRollover(rendered); - setPolicyName(rendered, 'mypolicy'); + await setPolicyName(rendered, 'mypolicy'); await activatePhase(rendered, 'warm'); expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy(); await openNodeAttributesSection(rendered, 'warm'); @@ -527,7 +566,7 @@ describe('edit policy', () => { test('should show node attributes input when attributes exist', async () => { const rendered = mountWithIntl(component); await noRollover(rendered); - setPolicyName(rendered, 'mypolicy'); + await setPolicyName(rendered, 'mypolicy'); await activatePhase(rendered, 'warm'); expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy(); await openNodeAttributesSection(rendered, 'warm'); @@ -539,7 +578,7 @@ describe('edit policy', () => { test('should show view node attributes link when attribute selected and show flyout when clicked', async () => { const rendered = mountWithIntl(component); await noRollover(rendered); - setPolicyName(rendered, 'mypolicy'); + await setPolicyName(rendered, 'mypolicy'); await activatePhase(rendered, 'warm'); expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy(); await openNodeAttributesSection(rendered, 'warm'); @@ -568,7 +607,7 @@ describe('edit policy', () => { }); const rendered = mountWithIntl(component); await noRollover(rendered); - setPolicyName(rendered, 'mypolicy'); + await setPolicyName(rendered, 'mypolicy'); await activatePhase(rendered, 'warm'); expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy(); expect(findTestSubject(rendered, 'defaultAllocationWarning').exists()).toBeTruthy(); @@ -581,7 +620,7 @@ describe('edit policy', () => { }); const rendered = mountWithIntl(component); await noRollover(rendered); - setPolicyName(rendered, 'mypolicy'); + await setPolicyName(rendered, 'mypolicy'); await activatePhase(rendered, 'warm'); expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy(); expect(findTestSubject(rendered, 'defaultAllocationNotice').exists()).toBeTruthy(); @@ -594,7 +633,7 @@ describe('edit policy', () => { }); const rendered = mountWithIntl(component); await noRollover(rendered); - setPolicyName(rendered, 'mypolicy'); + await setPolicyName(rendered, 'mypolicy'); await activatePhase(rendered, 'warm'); expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy(); expect(findTestSubject(rendered, 'defaultAllocationNotice').exists()).toBeFalsy(); @@ -611,7 +650,7 @@ describe('edit policy', () => { test('should allow 0 for phase timing', async () => { const rendered = mountWithIntl(component); await noRollover(rendered); - setPolicyName(rendered, 'mypolicy'); + await setPolicyName(rendered, 'mypolicy'); await activatePhase(rendered, 'cold'); await setPhaseAfter(rendered, 'cold', '0'); waitForFormLibValidation(rendered); @@ -621,7 +660,7 @@ describe('edit policy', () => { test('should show positive number required error when trying to save cold phase with -1 for after', async () => { const rendered = mountWithIntl(component); await noRollover(rendered); - setPolicyName(rendered, 'mypolicy'); + await setPolicyName(rendered, 'mypolicy'); await activatePhase(rendered, 'cold'); await setPhaseAfter(rendered, 'cold', '-1'); waitForFormLibValidation(rendered); @@ -631,7 +670,7 @@ describe('edit policy', () => { server.respondImmediately = false; const rendered = mountWithIntl(component); await noRollover(rendered); - setPolicyName(rendered, 'mypolicy'); + await setPolicyName(rendered, 'mypolicy'); await activatePhase(rendered, 'cold'); expect(rendered.find('.euiLoadingSpinner').exists()).toBeTruthy(); expect(rendered.find('.euiCallOut--warning').exists()).toBeFalsy(); @@ -645,7 +684,7 @@ describe('edit policy', () => { }); const rendered = mountWithIntl(component); await noRollover(rendered); - setPolicyName(rendered, 'mypolicy'); + await setPolicyName(rendered, 'mypolicy'); await activatePhase(rendered, 'cold'); expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy(); await openNodeAttributesSection(rendered, 'cold'); @@ -655,7 +694,7 @@ describe('edit policy', () => { test('should show node attributes input when attributes exist', async () => { const rendered = mountWithIntl(component); await noRollover(rendered); - setPolicyName(rendered, 'mypolicy'); + await setPolicyName(rendered, 'mypolicy'); await activatePhase(rendered, 'cold'); expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy(); await openNodeAttributesSection(rendered, 'cold'); @@ -667,7 +706,7 @@ describe('edit policy', () => { test('should show view node attributes link when attribute selected and show flyout when clicked', async () => { const rendered = mountWithIntl(component); await noRollover(rendered); - setPolicyName(rendered, 'mypolicy'); + await setPolicyName(rendered, 'mypolicy'); await activatePhase(rendered, 'cold'); expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy(); await openNodeAttributesSection(rendered, 'cold'); @@ -689,7 +728,7 @@ describe('edit policy', () => { test('should show positive number required error when trying to save with -1 for index priority', async () => { const rendered = mountWithIntl(component); await noRollover(rendered); - setPolicyName(rendered, 'mypolicy'); + await setPolicyName(rendered, 'mypolicy'); await activatePhase(rendered, 'cold'); await setPhaseAfter(rendered, 'cold', '1'); await setPhaseIndexPriority(rendered, 'cold', '-1'); @@ -704,7 +743,7 @@ describe('edit policy', () => { }); const rendered = mountWithIntl(component); await noRollover(rendered); - setPolicyName(rendered, 'mypolicy'); + await setPolicyName(rendered, 'mypolicy'); await activatePhase(rendered, 'cold'); expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy(); expect(findTestSubject(rendered, 'defaultAllocationWarning').exists()).toBeTruthy(); @@ -717,7 +756,7 @@ describe('edit policy', () => { }); const rendered = mountWithIntl(component); await noRollover(rendered); - setPolicyName(rendered, 'mypolicy'); + await setPolicyName(rendered, 'mypolicy'); await activatePhase(rendered, 'cold'); expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy(); expect(findTestSubject(rendered, 'defaultAllocationNotice').exists()).toBeTruthy(); @@ -730,7 +769,7 @@ describe('edit policy', () => { }); const rendered = mountWithIntl(component); await noRollover(rendered); - setPolicyName(rendered, 'mypolicy'); + await setPolicyName(rendered, 'mypolicy'); await activatePhase(rendered, 'cold'); expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy(); expect(findTestSubject(rendered, 'defaultAllocationNotice').exists()).toBeFalsy(); @@ -740,20 +779,20 @@ describe('edit policy', () => { test('should allow 0 for phase timing', async () => { const rendered = mountWithIntl(component); await noRollover(rendered); - setPolicyName(rendered, 'mypolicy'); + await setPolicyName(rendered, 'mypolicy'); await activatePhase(rendered, 'delete'); - setPhaseAfterLegacy(rendered, 'delete', '0'); - await save(rendered); + await setPhaseAfter(rendered, 'delete', '0'); + waitForFormLibValidation(rendered); expectedErrorMessages(rendered, []); }); test('should show positive number required error when trying to save delete phase with -1 for after', async () => { const rendered = mountWithIntl(component); await noRollover(rendered); - setPolicyName(rendered, 'mypolicy'); + await setPolicyName(rendered, 'mypolicy'); await activatePhase(rendered, 'delete'); - setPhaseAfterLegacy(rendered, 'delete', '-1'); - await save(rendered); - expectedErrorMessages(rendered, [positiveNumberRequiredMessage]); + await setPhaseAfter(rendered, 'delete', '-1'); + waitForFormLibValidation(rendered); + expectedErrorMessages(rendered, [i18nTexts.editPolicy.errors.nonNegativeNumberRequired]); }); }); describe('not on cloud', () => { @@ -768,7 +807,7 @@ describe('edit policy', () => { }); const rendered = mountWithIntl(component); await noRollover(rendered); - setPolicyName(rendered, 'mypolicy'); + await setPolicyName(rendered, 'mypolicy'); await activatePhase(rendered, 'warm'); expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy(); @@ -782,14 +821,13 @@ describe('edit policy', () => { describe('on cloud', () => { beforeEach(() => { component = ( - - - + ); ({ http } = editPolicyHelpers.setup()); ({ server, httpRequestsMockHelpers } = http); @@ -808,7 +846,7 @@ describe('edit policy', () => { }); const rendered = mountWithIntl(component); await noRollover(rendered); - setPolicyName(rendered, 'mypolicy'); + await setPolicyName(rendered, 'mypolicy'); await activatePhase(rendered, 'warm'); expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy(); @@ -829,7 +867,7 @@ describe('edit policy', () => { }); const rendered = mountWithIntl(component); await noRollover(rendered); - setPolicyName(rendered, 'mypolicy'); + await setPolicyName(rendered, 'mypolicy'); await activatePhase(rendered, 'warm'); expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy(); @@ -849,7 +887,7 @@ describe('edit policy', () => { }); const rendered = mountWithIntl(component); await noRollover(rendered); - setPolicyName(rendered, 'mypolicy'); + await setPolicyName(rendered, 'mypolicy'); await activatePhase(rendered, 'cold'); expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy(); expect(findTestSubject(rendered, 'cloudDataTierCallout').exists()).toBeTruthy(); diff --git a/x-pack/plugins/index_lifecycle_management/public/application/app.tsx b/x-pack/plugins/index_lifecycle_management/public/application/app.tsx index 856981fe5c4f9..20185b02064bc 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/app.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/app.tsx @@ -15,7 +15,7 @@ import { PolicyTable } from './sections/policy_table'; import { trackUiMetric } from './services/ui_metric'; import { ROUTES } from './services/navigation'; -export const App = ({ +export const AppWithRouter = ({ history, navigateToApp, getUrlForApp, @@ -23,23 +23,33 @@ export const App = ({ history: ScopedHistory; navigateToApp: ApplicationStart['navigateToApp']; getUrlForApp: ApplicationStart['getUrlForApp']; +}) => ( + + + +); + +export const App = ({ + navigateToApp, + getUrlForApp, +}: { + navigateToApp: ApplicationStart['navigateToApp']; + getUrlForApp: ApplicationStart['getUrlForApp']; }) => { useEffect(() => trackUiMetric(METRIC_TYPE.LOADED, UIM_APP_LOAD), []); return ( - - - - } - /> - } - /> - - + + + } + /> + } + /> + ); }; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/index.tsx b/x-pack/plugins/index_lifecycle_management/public/application/index.tsx index 3d4cc7dbbd1d4..bb1a4810ba2d2 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/index.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/index.tsx @@ -12,7 +12,7 @@ import { CloudSetup } from '../../../cloud/public'; import { KibanaContextProvider } from '../shared_imports'; -import { App } from './app'; +import { AppWithRouter } from './app'; import { BreadcrumbService } from './services/breadcrumbs'; @@ -28,7 +28,11 @@ export const renderApp = ( render( - + , element diff --git a/x-pack/plugins/index_lifecycle_management/public/application/lib/policies.ts b/x-pack/plugins/index_lifecycle_management/public/application/lib/policies.ts new file mode 100644 index 0000000000000..c4a91978a3765 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/public/application/lib/policies.ts @@ -0,0 +1,32 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { PolicyFromES } from '../../../common/types'; + +export const splitSizeAndUnits = (field: string): { size: string; units: string } => { + let size = ''; + let units = ''; + + const result = /(\d+)(\w+)/.exec(field); + if (result) { + size = result[1]; + units = result[2]; + } + + return { + size, + units, + }; +}; + +export const getPolicyByName = ( + policies: PolicyFromES[] | null | undefined, + policyName: string = '' +): PolicyFromES | undefined => { + if (policies && policies.length > 0) { + return policies.find((policy: PolicyFromES) => policy.name === policyName); + } +}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/index.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/index.ts index a04608338718e..326f6ff87dc3b 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/index.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/index.ts @@ -7,11 +7,8 @@ export { ActiveBadge } from './active_badge'; export { ErrableFormRow } from './form_errors'; export { LearnMoreLink } from './learn_more_link'; -export { MinAgeInput } from './min_age_input_legacy'; export { OptionalLabel } from './optional_label'; -export { PhaseErrorMessage } from './phase_error_message'; export { PolicyJsonFlyout } from './policy_json_flyout'; -export { SnapshotPolicies } from './snapshot_policies'; export { DescribedFormField } from './described_form_field'; export * from './phases'; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/min_age_input_legacy.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/min_age_input_legacy.tsx deleted file mode 100644 index 6fcf35b799289..0000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/min_age_input_legacy.tsx +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -import React from 'react'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { i18n } from '@kbn/i18n'; - -import { EuiFieldNumber, EuiFlexGroup, EuiFlexItem, EuiFormRow, EuiSelect } from '@elastic/eui'; - -import { LearnMoreLink } from './learn_more_link'; -import { ErrableFormRow } from './form_errors'; -import { PhaseValidationErrors, propertyof } from '../../../services/policies/policy_validation'; -import { PhaseWithMinAge, Phases } from '../../../../../common/types'; - -function getTimingLabelForPhase(phase: keyof Phases) { - // NOTE: Hot phase isn't necessary, because indices begin in the hot phase. - switch (phase) { - case 'warm': - return i18n.translate('xpack.indexLifecycleMgmt.editPolicy.phaseWarm.minimumAgeLabel', { - defaultMessage: 'Timing for warm phase', - }); - - case 'cold': - return i18n.translate('xpack.indexLifecycleMgmt.editPolicy.phaseCold.minimumAgeLabel', { - defaultMessage: 'Timing for cold phase', - }); - - case 'delete': - return i18n.translate('xpack.indexLifecycleMgmt.editPolicy.phaseDelete.minimumAgeLabel', { - defaultMessage: 'Timing for delete phase', - }); - } -} - -function getUnitsAriaLabelForPhase(phase: keyof Phases) { - // NOTE: Hot phase isn't necessary, because indices begin in the hot phase. - switch (phase) { - case 'warm': - return i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.phaseWarm.minimumAgeUnitsAriaLabel', - { - defaultMessage: 'Units for timing of warm phase', - } - ); - - case 'cold': - return i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.phaseCold.minimumAgeUnitsAriaLabel', - { - defaultMessage: 'Units for timing of cold phase', - } - ); - - case 'delete': - return i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.phaseDelete.minimumAgeUnitsAriaLabel', - { - defaultMessage: 'Units for timing of delete phase', - } - ); - } -} - -interface Props { - rolloverEnabled: boolean; - errors?: PhaseValidationErrors; - phase: keyof Phases & string; - phaseData: T; - setPhaseData: (dataKey: keyof T & string, value: string) => void; - isShowingErrors: boolean; -} - -export const MinAgeInput = ({ - rolloverEnabled, - errors, - phaseData, - phase, - setPhaseData, - isShowingErrors, -}: React.PropsWithChildren>): React.ReactElement => { - let daysOptionLabel; - let hoursOptionLabel; - let minutesOptionLabel; - let secondsOptionLabel; - let millisecondsOptionLabel; - let microsecondsOptionLabel; - let nanosecondsOptionLabel; - - if (rolloverEnabled) { - daysOptionLabel = i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.rolloverDaysOptionLabel', - { - defaultMessage: 'days from rollover', - } - ); - - hoursOptionLabel = i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.rolloverHoursOptionLabel', - { - defaultMessage: 'hours from rollover', - } - ); - minutesOptionLabel = i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.rolloverMinutesOptionLabel', - { - defaultMessage: 'minutes from rollover', - } - ); - - secondsOptionLabel = i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.rolloverSecondsOptionLabel', - { - defaultMessage: 'seconds from rollover', - } - ); - millisecondsOptionLabel = i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.rolloverMilliSecondsOptionLabel', - { - defaultMessage: 'milliseconds from rollover', - } - ); - - microsecondsOptionLabel = i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.rolloverMicroSecondsOptionLabel', - { - defaultMessage: 'microseconds from rollover', - } - ); - - nanosecondsOptionLabel = i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.rolloverNanoSecondsOptionLabel', - { - defaultMessage: 'nanoseconds from rollover', - } - ); - } else { - daysOptionLabel = i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.creationDaysOptionLabel', - { - defaultMessage: 'days from index creation', - } - ); - - hoursOptionLabel = i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.creationHoursOptionLabel', - { - defaultMessage: 'hours from index creation', - } - ); - - minutesOptionLabel = i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.creationMinutesOptionLabel', - { - defaultMessage: 'minutes from index creation', - } - ); - - secondsOptionLabel = i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.creationSecondsOptionLabel', - { - defaultMessage: 'seconds from index creation', - } - ); - - millisecondsOptionLabel = i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.creationMilliSecondsOptionLabel', - { - defaultMessage: 'milliseconds from index creation', - } - ); - - microsecondsOptionLabel = i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.creationMicroSecondsOptionLabel', - { - defaultMessage: 'microseconds from index creation', - } - ); - - nanosecondsOptionLabel = i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.creationNanoSecondsOptionLabel', - { - defaultMessage: 'nanoseconds from index creation', - } - ); - } - - // check that these strings are valid properties - const selectedMinimumAgeProperty = propertyof('selectedMinimumAge'); - const selectedMinimumAgeUnitsProperty = propertyof('selectedMinimumAgeUnits'); - return ( - - - - } - /> - } - > - { - setPhaseData(selectedMinimumAgeProperty, e.target.value); - }} - min={0} - /> - - - - - setPhaseData(selectedMinimumAgeUnitsProperty, e.target.value)} - options={[ - { - value: 'd', - text: daysOptionLabel, - }, - { - value: 'h', - text: hoursOptionLabel, - }, - { - value: 'm', - text: minutesOptionLabel, - }, - { - value: 's', - text: secondsOptionLabel, - }, - { - value: 'ms', - text: millisecondsOptionLabel, - }, - { - value: 'micros', - text: microsecondsOptionLabel, - }, - { - value: 'nanos', - text: nanosecondsOptionLabel, - }, - ]} - /> - - - - ); -}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phase_error_message.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phase_error_message.tsx deleted file mode 100644 index 750f68543f221..0000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phase_error_message.tsx +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -import React from 'react'; -import { EuiBadge } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; - -export const PhaseErrorMessage = ({ isShowingErrors }: { isShowingErrors: boolean }) => { - return isShowingErrors ? ( - - - - ) : null; -}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase/cold_phase.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase/cold_phase.tsx index 84e955a91ad7c..b87243bd1a9a1 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase/cold_phase.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase/cold_phase.tsx @@ -13,19 +13,13 @@ import { EuiDescribedFormGroup, EuiTextColor } from '@elastic/eui'; import { Phases } from '../../../../../../../common/types'; -import { - useFormData, - useFormContext, - UseField, - ToggleField, - NumericField, -} from '../../../../../../shared_imports'; +import { useFormData, UseField, ToggleField, NumericField } from '../../../../../../shared_imports'; import { useEditPolicyContext } from '../../../edit_policy_context'; -import { LearnMoreLink, ActiveBadge, PhaseErrorMessage, DescribedFormField } from '../../'; +import { LearnMoreLink, ActiveBadge, DescribedFormField } from '../../'; -import { MinAgeInputField, DataTierAllocationField, SetPriorityInput } from '../shared'; +import { MinAgeInputField, DataTierAllocationField, SetPriorityInput } from '../shared_fields'; const i18nTexts = { dataTierAllocation: { @@ -43,15 +37,13 @@ const formFieldPaths = { }; export const ColdPhase: FunctionComponent = () => { - const { originalPolicy } = useEditPolicyContext(); - const form = useFormContext(); + const { policy } = useEditPolicyContext(); const [formData] = useFormData({ watch: [formFieldPaths.enabled], }); const enabled = get(formData, formFieldPaths.enabled); - const isShowingErrors = form.isValid === false; return (
@@ -66,8 +58,7 @@ export const ColdPhase: FunctionComponent = () => { defaultMessage="Cold phase" /> {' '} - {enabled && !isShowingErrors ? : null} - + {enabled && }
} titleSize="s" @@ -128,9 +119,7 @@ export const ColdPhase: FunctionComponent = () => { 'xpack.indexLifecycleMgmt.editPolicy.coldPhase.numberOfReplicas.switchLabel', { defaultMessage: 'Set replicas' } ), - initialValue: Boolean( - originalPolicy.phases.cold?.actions?.allocate?.number_of_replicas - ), + initialValue: Boolean(policy.phases.cold?.actions?.allocate?.number_of_replicas), }} fullWidth > diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/delete_phase.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/delete_phase/delete_phase.tsx similarity index 50% rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/delete_phase.tsx rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/delete_phase/delete_phase.tsx index 78ae66327654c..37323b97edc92 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/delete_phase.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/delete_phase/delete_phase.tsx @@ -7,53 +7,24 @@ import React, { FunctionComponent, Fragment } from 'react'; import { get } from 'lodash'; import { FormattedMessage } from '@kbn/i18n/react'; -import { EuiDescribedFormGroup, EuiSwitch, EuiTextColor, EuiFormRow } from '@elastic/eui'; +import { EuiDescribedFormGroup, EuiTextColor, EuiFormRow } from '@elastic/eui'; -import { DeletePhase as DeletePhaseInterface, Phases } from '../../../../../../common/types'; +import { useFormData, UseField, ToggleField } from '../../../../../../shared_imports'; -import { useFormData } from '../../../../../shared_imports'; +import { ActiveBadge, LearnMoreLink, OptionalLabel } from '../../index'; -import { PhaseValidationErrors } from '../../../../services/policies/policy_validation'; +import { MinAgeInputField, SnapshotPoliciesField } from '../shared_fields'; -import { - ActiveBadge, - LearnMoreLink, - OptionalLabel, - PhaseErrorMessage, - MinAgeInput, - SnapshotPolicies, -} from '../'; -import { useRolloverPath } from './shared'; - -const deleteProperty: keyof Phases = 'delete'; -const phaseProperty = (propertyName: keyof DeletePhaseInterface) => propertyName; - -interface Props { - setPhaseData: (key: keyof DeletePhaseInterface & string, value: string | boolean) => void; - phaseData: DeletePhaseInterface; - isShowingErrors: boolean; - errors?: PhaseValidationErrors; - getUrlForApp: ( - appId: string, - options?: { - path?: string; - absolute?: boolean; - } - ) => string; -} +const formFieldPaths = { + enabled: '_meta.delete.enabled', +}; -export const DeletePhase: FunctionComponent = ({ - setPhaseData, - phaseData, - errors, - isShowingErrors, - getUrlForApp, -}) => { +export const DeletePhase: FunctionComponent = () => { const [formData] = useFormData({ - watch: useRolloverPath, + watch: formFieldPaths.enabled, }); - const hotPhaseRolloverEnabled = get(formData, useRolloverPath); + const enabled = get(formData, formFieldPaths.enabled); return (
@@ -66,8 +37,7 @@ export const DeletePhase: FunctionComponent = ({ defaultMessage="Delete phase" /> {' '} - {phaseData.phaseEnabled && !isShowingErrors ? : null} - + {enabled && }
} titleSize="s" @@ -79,39 +49,23 @@ export const DeletePhase: FunctionComponent = ({ defaultMessage="You no longer need your index. You can define when it is safe to delete it." />

- - } - id={`${deleteProperty}-${phaseProperty('phaseEnabled')}`} - checked={phaseData.phaseEnabled} - onChange={(e) => { - setPhaseData(phaseProperty('phaseEnabled'), e.target.checked); + } fullWidth > - {phaseData.phaseEnabled ? ( - - errors={errors} - phaseData={phaseData} - phase={deleteProperty} - isShowingErrors={isShowingErrors} - setPhaseData={setPhaseData} - rolloverEnabled={hotPhaseRolloverEnabled} - /> - ) : ( -
- )} + {enabled && } - {phaseData.phaseEnabled ? ( + {enabled ? ( @@ -145,11 +99,7 @@ export const DeletePhase: FunctionComponent = ({ } > - setPhaseData(phaseProperty('waitForSnapshotPolicy'), value)} - getUrlForApp={getUrlForApp} - /> + ) : null} diff --git a/x-pack/plugins/rollup/server/lib/__tests__/fixtures/index.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/delete_phase/index.ts similarity index 84% rename from x-pack/plugins/rollup/server/lib/__tests__/fixtures/index.js rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/delete_phase/index.ts index e97606c1fadfb..488e4e26cfce0 100644 --- a/x-pack/plugins/rollup/server/lib/__tests__/fixtures/index.js +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/delete_phase/index.ts @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export { jobs } from './jobs'; +export { DeletePhase } from './delete_phase'; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/hot_phase/hot_phase.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/hot_phase/hot_phase.tsx index a184ddf5148b9..629c1388f61fb 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/hot_phase/hot_phase.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/hot_phase/hot_phase.tsx @@ -19,7 +19,6 @@ import { import { Phases } from '../../../../../../../common/types'; import { - useFormContext, useFormData, UseField, SelectField, @@ -29,26 +28,24 @@ import { import { i18nTexts } from '../../../i18n_texts'; -import { ROLLOVER_EMPTY_VALIDATION } from '../../../form_validations'; +import { ROLLOVER_EMPTY_VALIDATION } from '../../../form'; import { ROLLOVER_FORM_PATHS } from '../../../constants'; -import { LearnMoreLink, ActiveBadge, PhaseErrorMessage } from '../../'; +import { LearnMoreLink, ActiveBadge } from '../../'; -import { Forcemerge, SetPriorityInput, useRolloverPath } from '../shared'; +import { Forcemerge, SetPriorityInput, useRolloverPath } from '../shared_fields'; import { maxSizeStoredUnits, maxAgeUnits } from './constants'; const hotProperty: keyof Phases = 'hot'; export const HotPhase: FunctionComponent = () => { - const form = useFormContext(); const [formData] = useFormData({ watch: useRolloverPath, }); const isRolloverEnabled = get(formData, useRolloverPath); - const isShowingErrors = form.isValid === false; const [showEmptyRolloverFieldsError, setShowEmptyRolloverFieldsError] = useState(false); return ( @@ -62,8 +59,7 @@ export const HotPhase: FunctionComponent = () => { defaultMessage="Hot phase" /> {' '} - {isShowingErrors ? null : } - +
} titleSize="s" diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/cloud_data_tier_callout.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/cloud_data_tier_callout.tsx similarity index 100% rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/cloud_data_tier_callout.tsx rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/cloud_data_tier_callout.tsx diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/data_tier_allocation.scss b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/data_tier_allocation.scss similarity index 100% rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/data_tier_allocation.scss rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/data_tier_allocation.scss diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/data_tier_allocation.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/data_tier_allocation.tsx similarity index 100% rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/data_tier_allocation.tsx rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/data_tier_allocation.tsx diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/default_allocation_notice.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/default_allocation_notice.tsx similarity index 100% rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/default_allocation_notice.tsx rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/default_allocation_notice.tsx diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/index.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/index.ts similarity index 100% rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/index.ts rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/index.ts diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/no_node_attributes_warning.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/no_node_attributes_warning.tsx similarity index 100% rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/no_node_attributes_warning.tsx rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/no_node_attributes_warning.tsx diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/node_allocation.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/node_allocation.tsx similarity index 90% rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/node_allocation.tsx rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/node_allocation.tsx index 407bb9ea92e85..c1676d7074dbc 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/node_allocation.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/node_allocation.tsx @@ -10,12 +10,8 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; import { EuiButtonEmpty, EuiText, EuiSpacer } from '@elastic/eui'; -import { PhaseWithAllocationAction } from '../../../../../../../../../common/types'; - import { UseField, SelectField, useFormData } from '../../../../../../../../shared_imports'; -import { propertyof } from '../../../../../../../services/policies/policy_validation'; - import { LearnMoreLink } from '../../../../learn_more_link'; import { NodeAttrsDetails } from './node_attrs_details'; @@ -61,9 +57,6 @@ export const NodeAllocation: FunctionComponent = ({ phase, nodes }) nodeOptions.sort((a, b) => a.value.localeCompare(b.value)); - // check that this string is a valid property - const nodeAttrsProperty = propertyof('selectedNodeAttrs'); - return ( <> @@ -100,7 +93,7 @@ export const NodeAllocation: FunctionComponent = ({ phase, nodes }) ) : undefined, euiFieldProps: { - 'data-test-subj': `${phase}-${nodeAttrsProperty}`, + 'data-test-subj': `${phase}-selectedNodeAttrs`, options: [{ text: i18nTexts.doNotModifyAllocationOption, value: '' }].concat( nodeOptions ), diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/node_attrs_details.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/node_attrs_details.tsx similarity index 100% rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/node_attrs_details.tsx rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/node_attrs_details.tsx diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/node_data_provider.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/node_data_provider.tsx similarity index 100% rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/node_data_provider.tsx rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/node_data_provider.tsx diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/types.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/types.ts similarity index 100% rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/types.ts rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/types.ts diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/data_tier_allocation_field.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/data_tier_allocation_field.tsx similarity index 100% rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/data_tier_allocation_field.tsx rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/data_tier_allocation_field.tsx diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/index.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/index.ts similarity index 100% rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/index.ts rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/index.ts diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/forcemerge_field.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/forcemerge_field.tsx similarity index 94% rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/forcemerge_field.tsx rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/forcemerge_field.tsx index b410bd0e6b3b0..b05d49be497cd 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/forcemerge_field.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/forcemerge_field.tsx @@ -21,11 +21,11 @@ interface Props { } export const Forcemerge: React.FunctionComponent = ({ phase }) => { - const { originalPolicy } = useEditPolicyContext(); + const { policy } = useEditPolicyContext(); const initialToggleValue = useMemo(() => { - return Boolean(originalPolicy.phases[phase]?.actions?.forcemerge); - }, [originalPolicy, phase]); + return Boolean(policy.phases[phase]?.actions?.forcemerge); + }, [policy, phase]); return ( = ({ phase }) => { - const phaseIndexPriorityProperty = propertyof('phaseIndexPriority'); return ( = ({ phase }) => { componentProps={{ fullWidth: false, euiFieldProps: { - 'data-test-subj': `${phase}-${phaseIndexPriorityProperty}`, - min: 1, + 'data-test-subj': `${phase}-phaseIndexPriority`, + min: 0, }, }} /> diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/snapshot_policies.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/snapshot_policies_field.tsx similarity index 68% rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/snapshot_policies.tsx rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/snapshot_policies_field.tsx index cc2849b5c8e9c..e9f9f331e410a 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/snapshot_policies.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/snapshot_policies_field.tsx @@ -4,52 +4,39 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { Fragment } from 'react'; - +import React from 'react'; +import { get } from 'lodash'; import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; -import { ApplicationStart } from 'kibana/public'; import { EuiButtonIcon, EuiCallOut, - EuiComboBox, EuiComboBoxOptionOption, EuiLink, EuiSpacer, } from '@elastic/eui'; -import { useLoadSnapshotPolicies } from '../../../services/api'; +import { UseField, ComboBoxField, useFormData } from '../../../../../../shared_imports'; +import { useLoadSnapshotPolicies } from '../../../../../services/api'; +import { useEditPolicyContext } from '../../../edit_policy_context'; + +const waitForSnapshotFormField = 'phases.delete.actions.wait_for_snapshot.policy'; -interface Props { - value: string; - onChange: (value: string) => void; - getUrlForApp: ApplicationStart['getUrlForApp']; -} -export const SnapshotPolicies: React.FunctionComponent = ({ - value, - onChange, - getUrlForApp, -}) => { +export const SnapshotPoliciesField: React.FunctionComponent = () => { + const { getUrlForApp } = useEditPolicyContext(); const { error, isLoading, data, resendRequest } = useLoadSnapshotPolicies(); + const [formData] = useFormData({ + watch: waitForSnapshotFormField, + }); + + const selectedSnapshotPolicy = get(formData, waitForSnapshotFormField); const policies = data.map((name: string) => ({ label: name, value: name, })); - const onComboChange = (options: EuiComboBoxOptionOption[]) => { - if (options.length > 0) { - onChange(options[0].label); - } else { - onChange(''); - } - }; - - const onCreateOption = (newValue: string) => { - onChange(newValue); - }; - const getUrlForSnapshotPolicyWizard = () => { return getUrlForApp('management', { path: `data/snapshot_restore/add_policy`, @@ -59,14 +46,14 @@ export const SnapshotPolicies: React.FunctionComponent = ({ let calloutContent; if (error) { calloutContent = ( - + <> + <> = ({ } )} /> - + } > = ({ defaultMessage="Refresh this field and enter the name of an existing snapshot policy." /> - + ); } else if (data.length === 0) { calloutContent = ( - + <> = ({ }} /> - + ); - } else if (value && !data.includes(value)) { + } else if (selectedSnapshotPolicy && !data.includes(selectedSnapshotPolicy)) { calloutContent = ( - + <> = ({ }} /> - + ); } return ( - - + path={waitForSnapshotFormField}> + {(field) => { + const singleSelectionArray: [selectedSnapshot?: string] = field.value + ? [field.value] + : []; + + return ( + { + field.setValue(newOption); }, - ] - : [] - } - onChange={onComboChange} - noSuggestions={!!(error || data.length === 0)} - /> + onChange: (options: EuiComboBoxOptionOption[]) => { + if (options.length > 0) { + field.setValue(options[0].label); + } else { + field.setValue(''); + } + }, + }} + /> + ); + }} +
{calloutContent} - + ); }; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/warm_phase/warm_phase.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/warm_phase/warm_phase.tsx index 06c16e8bdd5ab..94fd2ee9edaca 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/warm_phase/warm_phase.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/warm_phase/warm_phase.tsx @@ -17,23 +17,17 @@ import { EuiDescribedFormGroup, } from '@elastic/eui'; -import { - useFormData, - UseField, - ToggleField, - useFormContext, - NumericField, -} from '../../../../../../shared_imports'; +import { useFormData, UseField, ToggleField, NumericField } from '../../../../../../shared_imports'; import { Phases } from '../../../../../../../common/types'; -import { useRolloverPath, MinAgeInputField, Forcemerge, SetPriorityInput } from '../shared'; +import { useRolloverPath, MinAgeInputField, Forcemerge, SetPriorityInput } from '../shared_fields'; import { useEditPolicyContext } from '../../../edit_policy_context'; -import { LearnMoreLink, ActiveBadge, PhaseErrorMessage, DescribedFormField } from '../../'; +import { LearnMoreLink, ActiveBadge, DescribedFormField } from '../../'; -import { DataTierAllocationField } from '../shared'; +import { DataTierAllocationField } from '../shared_fields'; const i18nTexts = { shrinkLabel: i18n.translate('xpack.indexLifecycleMgmt.warmPhase.shrinkIndexLabel', { @@ -54,8 +48,7 @@ const formFieldPaths = { }; export const WarmPhase: FunctionComponent = () => { - const { originalPolicy } = useEditPolicyContext(); - const form = useFormContext(); + const { policy } = useEditPolicyContext(); const [formData] = useFormData({ watch: [useRolloverPath, formFieldPaths.enabled, formFieldPaths.warmPhaseOnRollover], }); @@ -63,7 +56,6 @@ export const WarmPhase: FunctionComponent = () => { const enabled = get(formData, formFieldPaths.enabled); const hotPhaseRolloverEnabled = get(formData, useRolloverPath); const warmPhaseOnRollover = get(formData, formFieldPaths.warmPhaseOnRollover); - const isShowingErrors = form.isValid === false; return (
@@ -77,8 +69,7 @@ export const WarmPhase: FunctionComponent = () => { defaultMessage="Warm phase" /> {' '} - {enabled && !isShowingErrors ? : null} - + {enabled && }
} titleSize="s" @@ -161,9 +152,7 @@ export const WarmPhase: FunctionComponent = () => { 'xpack.indexLifecycleMgmt.editPolicy.warmPhase.numberOfReplicas.switchLabel', { defaultMessage: 'Set replicas' } ), - initialValue: Boolean( - originalPolicy.phases.warm?.actions?.allocate?.number_of_replicas - ), + initialValue: Boolean(policy.phases.warm?.actions?.allocate?.number_of_replicas), }} fullWidth > @@ -203,7 +192,7 @@ export const WarmPhase: FunctionComponent = () => { 'data-test-subj': 'shrinkSwitch', label: i18nTexts.shrinkLabel, 'aria-label': i18nTexts.shrinkLabel, - initialValue: Boolean(originalPolicy.phases.warm?.actions?.shrink), + initialValue: Boolean(policy.phases.warm?.actions?.shrink), }} fullWidth > diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/policy_json_flyout.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/policy_json_flyout.tsx index 7098b018d6dfd..a8b1680ebde07 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/policy_json_flyout.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/policy_json_flyout.tsx @@ -7,7 +7,6 @@ import React, { useCallback, useEffect, useState } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; - import { EuiButtonEmpty, EuiCodeBlock, @@ -25,19 +24,15 @@ import { import { SerializedPolicy } from '../../../../../common/types'; import { useFormContext, useFormData } from '../../../../shared_imports'; + import { FormInternal } from '../types'; interface Props { - legacyPolicy: SerializedPolicy; close: () => void; policyName: string; } -export const PolicyJsonFlyout: React.FunctionComponent = ({ - policyName, - close, - legacyPolicy, -}) => { +export const PolicyJsonFlyout: React.FunctionComponent = ({ policyName, close }) => { /** * policy === undefined: we are checking validity * policy === null: we have determined the policy is invalid @@ -51,20 +46,11 @@ export const PolicyJsonFlyout: React.FunctionComponent = ({ const updatePolicy = useCallback(async () => { setPolicy(undefined); if (await validateForm()) { - const p = getFormData() as SerializedPolicy; - setPolicy({ - ...legacyPolicy, - phases: { - ...legacyPolicy.phases, - hot: p.phases.hot, - warm: p.phases.warm, - cold: p.phases.cold, - }, - }); + setPolicy(getFormData() as SerializedPolicy); } else { setPolicy(null); } - }, [setPolicy, getFormData, legacyPolicy, validateForm]); + }, [setPolicy, getFormData, validateForm]); useEffect(() => { updatePolicy(); diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy.container.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy.container.tsx index c82a420b74857..4c0cc2c8957e1 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy.container.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy.container.tsx @@ -9,11 +9,14 @@ import { RouteComponentProps } from 'react-router-dom'; import { EuiButton, EuiEmptyPrompt, EuiLoadingSpinner } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { useKibana } from '../../../shared_imports'; +import { useKibana, attemptToURIDecode } from '../../../shared_imports'; import { useLoadPoliciesList } from '../../services/api'; +import { getPolicyByName } from '../../lib/policies'; +import { defaultPolicy } from '../../constants'; import { EditPolicy as PresentationComponent } from './edit_policy'; +import { EditPolicyContextProvider } from './edit_policy_context'; interface RouterProps { policyName: string; @@ -44,6 +47,7 @@ export const EditPolicy: React.FunctionComponent { breadcrumbService.setBreadcrumbs('editPolicy'); }, [breadcrumbService]); + if (isLoading) { return ( + + + ); }; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy.tsx index 5397f5da2d6bb..1e462dcb680f2 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy.tsx @@ -4,7 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { Fragment, useEffect, useState, useCallback, useMemo } from 'react'; +import React, { Fragment, useEffect, useState, useMemo } from 'react'; +import { get } from 'lodash'; import { RouteComponentProps } from 'react-router-dom'; @@ -16,7 +17,6 @@ import { EuiButton, EuiButtonEmpty, EuiDescribedFormGroup, - EuiFieldText, EuiFlexGroup, EuiFlexItem, EuiFormRow, @@ -30,31 +30,13 @@ import { EuiTitle, } from '@elastic/eui'; -import { useForm, Form } from '../../../shared_imports'; +import { useForm, Form, UseField, TextField, useFormData } from '../../../shared_imports'; import { toasts } from '../../services/notification'; -import { LegacyPolicy, PolicyFromES, SerializedPolicy } from '../../../../common/types'; - -import { defaultPolicy } from '../../constants'; - -import { - validatePolicy, - ValidationErrors, - findFirstError, -} from '../../services/policies/policy_validation'; - -import { savePolicy } from '../../services/policies/policy_save'; +import { savePolicy } from './save_policy'; import { - deserializePolicy, - getPolicyByName, - initializeNewPolicy, - legacySerializePolicy, -} from '../../services/policies/policy_serialization'; - -import { - ErrableFormRow, LearnMoreLink, PolicyJsonFlyout, ColdPhase, @@ -63,93 +45,66 @@ import { WarmPhase, } from './components'; -import { schema } from './form_schema'; -import { deserializer } from './deserializer'; -import { createSerializer } from './serializer'; +import { schema, deserializer, createSerializer, createPolicyNameValidations } from './form'; -import { EditPolicyContextProvider } from './edit_policy_context'; +import { useEditPolicyContext } from './edit_policy_context'; +import { FormInternal } from './types'; export interface Props { - policies: PolicyFromES[]; - policyName: string; - getUrlForApp: ( - appId: string, - options?: { - path?: string; - absolute?: boolean; - } - ) => string; history: RouteComponentProps['history']; } -const mergeAllSerializedPolicies = ( - serializedPolicy: SerializedPolicy, - legacySerializedPolicy: SerializedPolicy -): SerializedPolicy => { - return { - ...legacySerializedPolicy, - phases: { - ...legacySerializedPolicy.phases, - hot: serializedPolicy.phases.hot, - warm: serializedPolicy.phases.warm, - cold: serializedPolicy.phases.cold, - }, - }; -}; +const policyNamePath = 'name'; -export const EditPolicy: React.FunctionComponent = ({ - policies, - policyName, - history, - getUrlForApp, -}) => { +export const EditPolicy: React.FunctionComponent = ({ history }) => { useEffect(() => { window.scrollTo(0, 0); }, []); - const [isShowingErrors, setIsShowingErrors] = useState(false); - const [errors, setErrors] = useState(); const [isShowingPolicyJsonFlyout, setIsShowingPolicyJsonFlyout] = useState(false); - - const existingPolicy = getPolicyByName(policies, policyName); + const { + isNewPolicy, + policy: currentPolicy, + existingPolicies, + policyName, + } = useEditPolicyContext(); const serializer = useMemo(() => { - return createSerializer(existingPolicy?.policy); - }, [existingPolicy?.policy]); + return createSerializer(isNewPolicy ? undefined : currentPolicy); + }, [isNewPolicy, currentPolicy]); - const originalPolicy = existingPolicy?.policy ?? defaultPolicy; + const [saveAsNew, setSaveAsNew] = useState(isNewPolicy); + const originalPolicyName: string = isNewPolicy ? '' : policyName!; const { form } = useForm({ schema, - defaultValue: originalPolicy, + defaultValue: { + ...currentPolicy, + name: originalPolicyName, + }, deserializer, serializer, }); - const [policy, setPolicy] = useState(() => - existingPolicy ? deserializePolicy(existingPolicy) : initializeNewPolicy(policyName) + const [formData] = useFormData({ form, watch: policyNamePath }); + const currentPolicyName = get(formData, policyNamePath); + + const policyNameValidations = useMemo( + () => + createPolicyNameValidations({ + originalPolicyName, + policies: existingPolicies, + saveAsNewPolicy: saveAsNew, + }), + [originalPolicyName, existingPolicies, saveAsNew] ); - const isNewPolicy: boolean = !Boolean(existingPolicy); - const [saveAsNew, setSaveAsNew] = useState(isNewPolicy); - const originalPolicyName: string = existingPolicy ? existingPolicy.name : ''; - const backToPolicyList = () => { history.push('/policies'); }; const submit = async () => { - setIsShowingErrors(true); - const { data: formLibPolicy, isValid: newIsValid } = await form.submit(); - const [legacyIsValid, validationErrors] = validatePolicy( - saveAsNew, - policy, - policies, - originalPolicyName - ); - setErrors(validationErrors); - - const isValid = legacyIsValid && newIsValid; + const { data: policy, isValid } = await form.submit(); if (!isValid) { toasts.addDanger( @@ -157,22 +112,11 @@ export const EditPolicy: React.FunctionComponent = ({ defaultMessage: 'Please fix the errors on this page.', }) ); - // This functionality will not be required for once form lib is fully adopted for this form - // because errors are reported as fields are edited. - if (!legacyIsValid) { - const firstError = findFirstError(validationErrors); - const errorRowId = `${firstError ? firstError.replace('.', '-') : ''}-row`; - const element = document.getElementById(errorRowId); - if (element) { - element.scrollIntoView({ block: 'center', inline: 'nearest' }); - } - } } else { - const readSerializedPolicy = () => { - const legacySerializedPolicy = legacySerializePolicy(policy, existingPolicy?.policy); - return mergeAllSerializedPolicies(formLibPolicy, legacySerializedPolicy); - }; - const success = await savePolicy(readSerializedPolicy, isNewPolicy || saveAsNew); + const success = await savePolicy( + { ...policy, name: saveAsNew ? currentPolicyName : originalPolicyName }, + isNewPolicy || saveAsNew + ); if (success) { backToPolicyList(); } @@ -183,248 +127,217 @@ export const EditPolicy: React.FunctionComponent = ({ setIsShowingPolicyJsonFlyout(!isShowingPolicyJsonFlyout); }; - const setPhaseData = useCallback( - (phase: keyof LegacyPolicy['phases'], key: string, value: any) => { - setPolicy((nextPolicy) => ({ - ...nextPolicy, - phases: { - ...nextPolicy.phases, - [phase]: { ...nextPolicy.phases[phase], [key]: value }, - }, - })); - }, - [setPolicy] - ); - - const setDeletePhaseData = useCallback( - (key: string, value: any) => setPhaseData('delete', key, value), - [setPhaseData] - ); - return ( - - - - - -

- {isNewPolicy - ? i18n.translate('xpack.indexLifecycleMgmt.editPolicy.createPolicyMessage', { - defaultMessage: 'Create an index lifecycle policy', - }) - : i18n.translate('xpack.indexLifecycleMgmt.editPolicy.editPolicyMessage', { - defaultMessage: 'Edit index lifecycle policy {originalPolicyName}', - values: { originalPolicyName }, - })} -

-
- -
-
- - -

- + +

+ {isNewPolicy + ? i18n.translate('xpack.indexLifecycleMgmt.editPolicy.createPolicyMessage', { + defaultMessage: 'Create an index lifecycle policy', + }) + : i18n.translate('xpack.indexLifecycleMgmt.editPolicy.editPolicyMessage', { + defaultMessage: 'Edit index lifecycle policy {originalPolicyName}', + values: { originalPolicyName }, + })} +

+ + +
+ + + +

+ {' '} - - } - /> -

-
+ />{' '} + + } + /> +

+ - + - {isNewPolicy ? null : ( - - -

- - - - .{' '} + {isNewPolicy ? null : ( + + +

+ + + .{' '} + -

-
- - - - { - setSaveAsNew(e.target.checked); - }} - label={ - - - - } /> - -
- )} - - {saveAsNew || isNewPolicy ? ( - - +

+ + + + + { + setSaveAsNew(e.target.checked); + }} + label={ + -
- } - titleSize="s" - fullWidth - > - + + + )} + + {saveAsNew || isNewPolicy ? ( + + - } - > - { - setPolicy({ ...policy, name: e.target.value }); - }} - /> - - - ) : null} + +
+ } + titleSize="s" + fullWidth + > + + path={policyNamePath} + config={{ + label: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.policyNameLabel', { + defaultMessage: 'Policy name', + }), + helpText: i18n.translate( + 'xpack.indexLifecycleMgmt.editPolicy.validPolicyNameMessage', + { + defaultMessage: + 'A policy name cannot start with an underscore and cannot contain a question mark or a space.', + } + ), + validations: policyNameValidations, + }} + component={TextField} + componentProps={{ + fullWidth: false, + euiFieldProps: { + 'data-test-subj': 'policyNameField', + }, + }} + /> + + ) : null} - + - + - + - + - + - + - + - 0 - } - getUrlForApp={getUrlForApp} - setPhaseData={setDeletePhaseData} - phaseData={policy.phases.delete} - /> + - - - - - - - - {saveAsNew ? ( - - ) : ( - - )} - - - - - + + + + + + + + {saveAsNew ? ( - - - - - - - - {isShowingPolicyJsonFlyout ? ( - - ) : ( + ) : ( + + )} + + + + + - )} - - - - - {isShowingPolicyJsonFlyout ? ( - setIsShowingPolicyJsonFlyout(false)} - /> - ) : null} - -
- - - - + + + + + + + + {isShowingPolicyJsonFlyout ? ( + + ) : ( + + )} + + + + + {isShowingPolicyJsonFlyout ? ( + setIsShowingPolicyJsonFlyout(false)} + /> + ) : null} + + + + + ); }; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy_context.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy_context.tsx index 4748c26d6cec1..da5f940b1b6c8 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy_context.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy_context.tsx @@ -5,10 +5,16 @@ */ import React, { createContext, ReactChild, useContext } from 'react'; -import { SerializedPolicy } from '../../../../common/types'; +import { ApplicationStart } from 'kibana/public'; -interface EditPolicyContextValue { - originalPolicy: SerializedPolicy; +import { PolicyFromES, SerializedPolicy } from '../../../../common/types'; + +export interface EditPolicyContextValue { + isNewPolicy: boolean; + policy: SerializedPolicy; + existingPolicies: PolicyFromES[]; + getUrlForApp: ApplicationStart['getUrlForApp']; + policyName?: string; } const EditPolicyContext = createContext(null as any); diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/deserializer.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/deserializer.ts similarity index 82% rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/deserializer.ts rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/deserializer.ts index f0294a5391d21..5af8807f2dec8 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/deserializer.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/deserializer.ts @@ -6,17 +6,17 @@ import { produce } from 'immer'; -import { SerializedPolicy } from '../../../../common/types'; +import { SerializedPolicy } from '../../../../../common/types'; -import { splitSizeAndUnits } from '../../services/policies/policy_serialization'; +import { splitSizeAndUnits } from '../../../lib/policies'; -import { determineDataTierAllocationType } from '../../lib'; +import { determineDataTierAllocationType } from '../../../lib'; -import { FormInternal } from './types'; +import { FormInternal } from '../types'; export const deserializer = (policy: SerializedPolicy): FormInternal => { const { - phases: { hot, warm, cold }, + phases: { hot, warm, cold, delete: deletePhase }, } = policy; const _meta: FormInternal['_meta'] = { @@ -37,6 +37,9 @@ export const deserializer = (policy: SerializedPolicy): FormInternal => { dataTierAllocationType: determineDataTierAllocationType(cold?.actions), freezeEnabled: Boolean(cold?.actions?.freeze), }, + delete: { + enabled: Boolean(deletePhase), + }, }; return produce( @@ -86,6 +89,14 @@ export const deserializer = (policy: SerializedPolicy): FormInternal => { draft._meta.cold.minAgeUnit = minAge.units; } } + + if (draft.phases.delete) { + if (draft.phases.delete.min_age) { + const minAge = splitSizeAndUnits(draft.phases.delete.min_age); + draft.phases.delete.min_age = minAge.size; + draft._meta.delete.minAgeUnit = minAge.units; + } + } } ); }; diff --git a/x-pack/test/kerberos_api_integration/ftr_provider_context.d.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/index.ts similarity index 57% rename from x-pack/test/kerberos_api_integration/ftr_provider_context.d.ts rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/index.ts index e3add3748f56d..82fa478832582 100644 --- a/x-pack/test/kerberos_api_integration/ftr_provider_context.d.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/index.ts @@ -4,8 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import { GenericFtrProviderContext } from '@kbn/test/types/ftr'; +export { deserializer } from './deserializer'; -import { services } from './services'; +export { createSerializer } from './serializer'; -export type FtrProviderContext = GenericFtrProviderContext; +export { schema } from './schema'; + +export * from './validations'; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form_schema.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/schema.ts similarity index 90% rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form_schema.ts rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/schema.ts index 070f03f74b954..4d20db4018740 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form_schema.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/schema.ts @@ -6,18 +6,19 @@ import { i18n } from '@kbn/i18n'; -import { FormSchema, fieldValidators } from '../../../shared_imports'; -import { defaultSetPriority, defaultPhaseIndexPriority } from '../../constants'; +import { FormSchema, fieldValidators } from '../../../../shared_imports'; +import { defaultSetPriority, defaultPhaseIndexPriority } from '../../../constants'; -import { FormInternal } from './types'; +import { FormInternal } from '../types'; import { ifExistsNumberGreaterThanZero, ifExistsNumberNonNegative, rolloverThresholdsValidator, -} from './form_validations'; + minAgeValidator, +} from './validations'; -import { i18nTexts } from './i18n_texts'; +import { i18nTexts } from '../i18n_texts'; const { emptyField, numberGreaterThanField } = fieldValidators; @@ -97,6 +98,18 @@ export const schema: FormSchema = { label: i18nTexts.editPolicy.allocationNodeAttributeFieldLabel, }, }, + delete: { + enabled: { + defaultValue: false, + label: i18n.translate( + 'xpack.indexLifecycleMgmt.editPolicy.deletePhase.activateWarmPhaseSwitchLabel', + { defaultMessage: 'Activate delete phase' } + ), + }, + minAgeUnit: { + defaultValue: 'd', + }, + }, }, phases: { hot: { @@ -177,15 +190,7 @@ export const schema: FormSchema = { defaultValue: '0', validations: [ { - validator: (arg) => - numberGreaterThanField({ - than: 0, - allowEquality: true, - message: i18nTexts.editPolicy.errors.nonNegativeNumberRequired, - })({ - ...arg, - value: arg.value === '' ? -Infinity : parseInt(arg.value, 10), - }), + validator: minAgeValidator, }, ], }, @@ -256,15 +261,7 @@ export const schema: FormSchema = { defaultValue: '0', validations: [ { - validator: (arg) => - numberGreaterThanField({ - than: 0, - allowEquality: true, - message: i18nTexts.editPolicy.errors.nonNegativeNumberRequired, - })({ - ...arg, - value: arg.value === '' ? -Infinity : parseInt(arg.value, 10), - }), + validator: minAgeValidator, }, ], }, @@ -292,5 +289,15 @@ export const schema: FormSchema = { }, }, }, + delete: { + min_age: { + defaultValue: '0', + validations: [ + { + validator: minAgeValidator, + }, + ], + }, + }, }, }; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/serializer.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/serializer.ts similarity index 90% rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/serializer.ts rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/serializer.ts index 564b5a2c4e397..2274efda426ad 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/serializer.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/serializer.ts @@ -4,12 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ -import { isEmpty } from 'lodash'; +import { isEmpty, isNumber } from 'lodash'; -import { SerializedPolicy, SerializedActionWithAllocation } from '../../../../common/types'; +import { SerializedPolicy, SerializedActionWithAllocation } from '../../../../../common/types'; -import { FormInternal, DataAllocationMetaFields } from './types'; -import { isNumber } from '../../services/policies/policy_serialization'; +import { FormInternal, DataAllocationMetaFields } from '../types'; const serializeAllocateAction = ( { dataTierAllocationType, allocationNodeAttribute }: DataAllocationMetaFields, @@ -165,5 +164,22 @@ export const createSerializer = (originalPolicy?: SerializedPolicy) => ( } } + /** + * DELETE PHASE SERIALIZATION + */ + if (policy.phases.delete) { + if (policy.phases.delete.min_age) { + policy.phases.delete.min_age = `${policy.phases.delete.min_age}${_meta.delete.minAgeUnit}`; + } + + if (originalPolicy?.phases.delete?.actions) { + const { wait_for_snapshot: __, ...rest } = originalPolicy.phases.delete.actions; + policy.phases.delete.actions = { + ...policy.phases.delete.actions, + ...rest, + }; + } + } + return policy; }; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form_validations.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/validations.ts similarity index 50% rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form_validations.ts rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/validations.ts index 9c855ccb41624..f2e26a552efc9 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form_validations.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/validations.ts @@ -4,13 +4,15 @@ * you may not use this file except in compliance with the Elastic License. */ -import { fieldValidators, ValidationFunc } from '../../../shared_imports'; +import { fieldValidators, ValidationFunc, ValidationConfig } from '../../../../shared_imports'; -import { ROLLOVER_FORM_PATHS } from './constants'; +import { ROLLOVER_FORM_PATHS } from '../constants'; -import { i18nTexts } from './i18n_texts'; +import { i18nTexts } from '../i18n_texts'; +import { PolicyFromES } from '../../../../../common/types'; +import { FormInternal } from '../types'; -const { numberGreaterThanField } = fieldValidators; +const { numberGreaterThanField, containsCharsField, emptyField, startsWithField } = fieldValidators; const createIfNumberExistsValidator = ({ than, @@ -46,7 +48,7 @@ export const ifExistsNumberNonNegative = createIfNumberExistsValidator({ * A special validation type used to keep track of validation errors for * the rollover threshold values not being set (e.g., age and doc count) */ -export const ROLLOVER_EMPTY_VALIDATION = 'EMPTY'; +export const ROLLOVER_EMPTY_VALIDATION = 'ROLLOVER_EMPTY_VALIDATION'; /** * An ILM policy requires that for rollover a value must be set for one of the threshold values. @@ -87,3 +89,68 @@ export const rolloverThresholdsValidator: ValidationFunc = ({ form }) => { fields[ROLLOVER_FORM_PATHS.maxSize].clearErrors(ROLLOVER_EMPTY_VALIDATION); } }; + +export const minAgeValidator: ValidationFunc = (arg) => + numberGreaterThanField({ + than: 0, + allowEquality: true, + message: i18nTexts.editPolicy.errors.nonNegativeNumberRequired, + })({ + ...arg, + value: arg.value === '' ? -Infinity : parseInt(arg.value, 10), + }); + +export const createPolicyNameValidations = ({ + policies, + saveAsNewPolicy, + originalPolicyName, +}: { + policies: PolicyFromES[]; + saveAsNewPolicy: boolean; + originalPolicyName?: string; +}): Array> => { + return [ + { + validator: emptyField(i18nTexts.editPolicy.errors.policyNameRequiredMessage), + }, + { + validator: startsWithField({ + message: i18nTexts.editPolicy.errors.policyNameStartsWithUnderscoreErrorMessage, + char: '_', + }), + }, + { + validator: containsCharsField({ + message: i18nTexts.editPolicy.errors.policyNameContainsInvalidChars, + chars: [',', ' '], + }), + }, + { + validator: (arg) => { + const policyName = arg.value; + if (window.TextEncoder && new window.TextEncoder().encode(policyName).length > 255) { + return { + message: i18nTexts.editPolicy.errors.policyNameTooLongErrorMessage, + }; + } + }, + }, + { + validator: (arg) => { + const policyName = arg.value; + if (saveAsNewPolicy && policyName === originalPolicyName) { + return { + message: i18nTexts.editPolicy.errors.policyNameMustBeDifferentErrorMessage, + }; + } else if (policyName !== originalPolicyName) { + const policyNames = policies.map((existingPolicy) => existingPolicy.name); + if (policyNames.includes(policyName)) { + return { + message: i18nTexts.editPolicy.errors.policyNameAlreadyUsedErrorMessage, + }; + } + } + }, + }, + ]; +}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/i18n_texts.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/i18n_texts.ts index 1fba69b7634ae..ccd5d3a568fe3 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/i18n_texts.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/i18n_texts.ts @@ -98,6 +98,42 @@ export const i18nTexts = { defaultMessage: 'Only non-negative numbers are allowed.', } ), + policyNameContainsInvalidChars: i18n.translate( + 'xpack.indexLifecycleMgmt.editPolicy.errors.policyNameContainsInvalidCharsError', + { + defaultMessage: 'A policy name cannot contain spaces or commas.', + } + ), + policyNameAlreadyUsedErrorMessage: i18n.translate( + 'xpack.indexLifecycleMgmt.editPolicy.policyNameAlreadyUsedError', + { + defaultMessage: 'That policy name is already used.', + } + ), + policyNameMustBeDifferentErrorMessage: i18n.translate( + 'xpack.indexLifecycleMgmt.editPolicy.differentPolicyNameRequiredError', + { + defaultMessage: 'The policy name must be different.', + } + ), + policyNameRequiredMessage: i18n.translate( + 'xpack.indexLifecycleMgmt.editPolicy.policyNameRequiredError', + { + defaultMessage: 'A policy name is required.', + } + ), + policyNameStartsWithUnderscoreErrorMessage: i18n.translate( + 'xpack.indexLifecycleMgmt.editPolicy.policyNameStartsWithUnderscoreError', + { + defaultMessage: 'A policy name cannot start with an underscore.', + } + ), + policyNameTooLongErrorMessage: i18n.translate( + 'xpack.indexLifecycleMgmt.editPolicy.policyNameTooLongError', + { + defaultMessage: 'A policy name cannot be longer than 255 bytes.', + } + ), }, }, }; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_save.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/save_policy.ts similarity index 84% rename from x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_save.ts rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/save_policy.ts index 9cf622e830cb2..e2ab6a8817ef6 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_save.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/save_policy.ts @@ -3,23 +3,22 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - import { i18n } from '@kbn/i18n'; import { METRIC_TYPE } from '@kbn/analytics'; import { SerializedPolicy } from '../../../../common/types'; -import { savePolicy as savePolicyApi } from '../api'; -import { showApiError } from '../api_errors'; -import { getUiMetricsForPhases, trackUiMetric } from '../ui_metric'; + import { UIM_POLICY_CREATE, UIM_POLICY_UPDATE } from '../../constants'; -import { toasts } from '../notification'; + +import { toasts } from '../../services/notification'; +import { savePolicy as savePolicyApi } from '../../services/api'; +import { getUiMetricsForPhases, trackUiMetric } from '../../services/ui_metric'; +import { showApiError } from '../../services/api_errors'; export const savePolicy = async ( - readSerializedPolicy: () => SerializedPolicy, + serializedPolicy: SerializedPolicy, isNew: boolean ): Promise => { - const serializedPolicy = readSerializedPolicy(); - try { await savePolicyApi(serializedPolicy); } catch (err) { diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/types.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/types.ts index 1884f8dbc0619..dc3d8a640e682 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/types.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/types.ts @@ -38,6 +38,10 @@ interface ColdPhaseMetaFields extends DataAllocationMetaFields, MinAgeField { freezeEnabled: boolean; } +interface DeletePhaseMetaFields extends MinAgeField { + enabled: boolean; +} + /** * Describes the shape of data after deserialization. */ @@ -50,5 +54,6 @@ export interface FormInternal extends SerializedPolicy { hot: HotPhaseMetaFields; warm: WarmPhaseMetaFields; cold: ColdPhaseMetaFields; + delete: DeletePhaseMetaFields; }; } diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/delete_phase.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/policies/delete_phase.ts deleted file mode 100644 index 6ada039d45cd9..0000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/delete_phase.ts +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { DeletePhase, SerializedDeletePhase } from '../../../../common/types'; -import { serializedPhaseInitialization } from '../../constants'; -import { isNumber, splitSizeAndUnits } from './policy_serialization'; -import { - numberRequiredMessage, - PhaseValidationErrors, - positiveNumberRequiredMessage, -} from './policy_validation'; - -const deletePhaseInitialization: DeletePhase = { - phaseEnabled: false, - selectedMinimumAge: '0', - selectedMinimumAgeUnits: 'd', - waitForSnapshotPolicy: '', -}; - -export const deletePhaseFromES = (phaseSerialized?: SerializedDeletePhase): DeletePhase => { - const phase = { ...deletePhaseInitialization }; - if (phaseSerialized === undefined || phaseSerialized === null) { - return phase; - } - - phase.phaseEnabled = true; - if (phaseSerialized.min_age) { - const { size: minAge, units: minAgeUnits } = splitSizeAndUnits(phaseSerialized.min_age); - phase.selectedMinimumAge = minAge; - phase.selectedMinimumAgeUnits = minAgeUnits; - } - - if (phaseSerialized.actions) { - const actions = phaseSerialized.actions; - - if (actions.wait_for_snapshot) { - phase.waitForSnapshotPolicy = actions.wait_for_snapshot.policy; - } - } - - return phase; -}; - -export const deletePhaseToES = ( - phase: DeletePhase, - originalEsPhase?: SerializedDeletePhase -): SerializedDeletePhase => { - if (!originalEsPhase) { - originalEsPhase = { ...serializedPhaseInitialization }; - } - const esPhase = { ...originalEsPhase }; - - if (isNumber(phase.selectedMinimumAge)) { - esPhase.min_age = `${phase.selectedMinimumAge}${phase.selectedMinimumAgeUnits}`; - } - - esPhase.actions = esPhase.actions ? { ...esPhase.actions } : {}; - - if (phase.waitForSnapshotPolicy) { - esPhase.actions.wait_for_snapshot = { - policy: phase.waitForSnapshotPolicy, - }; - } else { - delete esPhase.actions.wait_for_snapshot; - } - - return esPhase; -}; - -export const validateDeletePhase = (phase: DeletePhase): PhaseValidationErrors => { - if (!phase.phaseEnabled) { - return {}; - } - - const phaseErrors = {} as PhaseValidationErrors; - - // min age needs to be a positive number - if (!isNumber(phase.selectedMinimumAge)) { - phaseErrors.selectedMinimumAge = [numberRequiredMessage]; - } else if (parseInt(phase.selectedMinimumAge, 10) < 0) { - phaseErrors.selectedMinimumAge = [positiveNumberRequiredMessage]; - } - - return { ...phaseErrors }; -}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_serialization.test.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_serialization.test.ts deleted file mode 100644 index 19481b39a2c80..0000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_serialization.test.ts +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -// Prefer importing entire lodash library, e.g. import { get } from "lodash" -// eslint-disable-next-line no-restricted-imports -import cloneDeep from 'lodash/cloneDeep'; -import { deserializePolicy, legacySerializePolicy } from './policy_serialization'; -import { defaultNewDeletePhase } from '../../constants'; - -describe('Policy serialization', () => { - test('serialize a policy using "default" data allocation', () => { - expect( - legacySerializePolicy( - { - name: 'test', - phases: { - delete: { ...defaultNewDeletePhase }, - }, - }, - { - name: 'test', - phases: { - hot: { actions: {} }, - }, - } - ) - ).toEqual({ - name: 'test', - phases: {}, - }); - }); - - test('serialize a policy using "custom" data allocation', () => { - expect( - legacySerializePolicy( - { - name: 'test', - phases: { - delete: { ...defaultNewDeletePhase }, - }, - }, - { - name: 'test', - phases: { - hot: { actions: {} }, - }, - } - ) - ).toEqual({ - name: 'test', - phases: {}, - }); - }); - - test('serialize a policy using "custom" data allocation with no node attributes', () => { - expect( - legacySerializePolicy( - { - name: 'test', - phases: { - delete: { ...defaultNewDeletePhase }, - }, - }, - { - name: 'test', - phases: { - hot: { actions: {} }, - }, - } - ) - ).toEqual({ - // There should be no allocation action in any phases... - name: 'test', - phases: {}, - }); - }); - - test('serialize a policy using "none" data allocation with no node attributes', () => { - expect( - legacySerializePolicy( - { - name: 'test', - phases: { - delete: { ...defaultNewDeletePhase }, - }, - }, - { - name: 'test', - phases: { - hot: { actions: {} }, - }, - } - ) - ).toEqual({ - // There should be no allocation action in any phases... - name: 'test', - phases: {}, - }); - }); - - test('serialization does not alter the original policy', () => { - const originalPolicy = { - name: 'test', - phases: {}, - }; - - const originalClone = cloneDeep(originalPolicy); - - const deserializedPolicy = { - name: 'test', - phases: { - delete: { ...defaultNewDeletePhase }, - }, - }; - - legacySerializePolicy(deserializedPolicy, originalPolicy); - expect(originalPolicy).toEqual(originalClone); - }); - - test('serialize a policy using "best_compression" codec for forcemerge', () => { - expect( - legacySerializePolicy( - { - name: 'test', - phases: { - delete: { ...defaultNewDeletePhase }, - }, - }, - { - name: 'test', - phases: { - hot: { actions: {} }, - }, - } - ) - ).toEqual({ - name: 'test', - phases: {}, - }); - }); - - test('de-serialize a policy using "best_compression" codec for forcemerge', () => { - expect( - deserializePolicy({ - modified_date: Date.now().toString(), - name: 'test', - version: 1, - policy: { - name: 'test', - phases: { - hot: { - actions: { - rollover: { - max_age: '30d', - max_size: '50gb', - }, - forcemerge: { - max_num_segments: 1, - index_codec: 'best_compression', - }, - set_priority: { - priority: 100, - }, - }, - }, - }, - }, - }) - ).toEqual({ - name: 'test', - phases: { - delete: { ...defaultNewDeletePhase }, - }, - }); - }); - - test('delete "best_compression" codec for forcemerge if disabled in UI', () => { - expect( - legacySerializePolicy( - { - name: 'test', - phases: { - delete: { ...defaultNewDeletePhase }, - }, - }, - { - name: 'test', - phases: {}, - } - ) - ).toEqual({ - name: 'test', - phases: {}, - }); - }); -}); diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_serialization.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_serialization.ts deleted file mode 100644 index 55e9d88dcd383..0000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_serialization.ts +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { LegacyPolicy, PolicyFromES, SerializedPolicy } from '../../../../common/types'; - -import { defaultNewDeletePhase, serializedPhaseInitialization } from '../../constants'; - -import { deletePhaseFromES, deletePhaseToES } from './delete_phase'; - -export const splitSizeAndUnits = (field: string): { size: string; units: string } => { - let size = ''; - let units = ''; - - const result = /(\d+)(\w+)/.exec(field); - if (result) { - size = result[1]; - units = result[2]; - } - - return { - size, - units, - }; -}; - -export const isNumber = (value: any): boolean => value !== '' && value !== null && isFinite(value); - -export const getPolicyByName = ( - policies: PolicyFromES[] | null | undefined, - policyName: string = '' -): PolicyFromES | undefined => { - if (policies && policies.length > 0) { - return policies.find((policy: PolicyFromES) => policy.name === policyName); - } -}; - -export const initializeNewPolicy = (newPolicyName: string = ''): LegacyPolicy => { - return { - name: newPolicyName, - phases: { - delete: { ...defaultNewDeletePhase }, - }, - }; -}; - -export const deserializePolicy = (policy: PolicyFromES): LegacyPolicy => { - const { - name, - policy: { phases }, - } = policy; - - return { - name, - phases: { - delete: deletePhaseFromES(phases.delete), - }, - }; -}; - -export const legacySerializePolicy = ( - policy: LegacyPolicy, - originalEsPolicy: SerializedPolicy = { - name: policy.name, - phases: { hot: { ...serializedPhaseInitialization } }, - } -): SerializedPolicy => { - const serializedPolicy = { - name: policy.name, - phases: {}, - } as SerializedPolicy; - - if (policy.phases.delete.phaseEnabled) { - serializedPolicy.phases.delete = deletePhaseToES( - policy.phases.delete, - originalEsPolicy.phases.delete - ); - } - return serializedPolicy; -}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_validation.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_validation.ts deleted file mode 100644 index 79c909c433f33..0000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_validation.ts +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { i18n } from '@kbn/i18n'; -import { DeletePhase, LegacyPolicy, PolicyFromES } from '../../../../common/types'; -import { validateDeletePhase } from './delete_phase'; - -export const propertyof = (propertyName: keyof T & string) => propertyName; - -export const numberRequiredMessage = i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.numberRequiredError', - { - defaultMessage: 'A number is required.', - } -); - -// TODO validation includes 0 -> should be non-negative number? -export const positiveNumberRequiredMessage = i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.positiveNumberRequiredError', - { - defaultMessage: 'Only positive numbers are allowed.', - } -); - -export const positiveNumbersAboveZeroErrorMessage = i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.positiveNumberAboveZeroRequiredError', - { - defaultMessage: 'Only numbers above 0 are allowed.', - } -); - -export const policyNameRequiredMessage = i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.policyNameRequiredError', - { - defaultMessage: 'A policy name is required.', - } -); - -export const policyNameStartsWithUnderscoreErrorMessage = i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.policyNameStartsWithUnderscoreError', - { - defaultMessage: 'A policy name cannot start with an underscore.', - } -); -export const policyNameContainsCommaErrorMessage = i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.policyNameContainsCommaError', - { - defaultMessage: 'A policy name cannot include a comma.', - } -); -export const policyNameContainsSpaceErrorMessage = i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.policyNameContainsSpaceError', - { - defaultMessage: 'A policy name cannot include a space.', - } -); - -export const policyNameTooLongErrorMessage = i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.policyNameTooLongError', - { - defaultMessage: 'A policy name cannot be longer than 255 bytes.', - } -); -export const policyNameMustBeDifferentErrorMessage = i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.differentPolicyNameRequiredError', - { - defaultMessage: 'The policy name must be different.', - } -); -export const policyNameAlreadyUsedErrorMessage = i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.policyNameAlreadyUsedError', - { - defaultMessage: 'That policy name is already used.', - } -); -export type PhaseValidationErrors = { - [P in keyof Partial]: string[]; -}; - -export interface ValidationErrors { - delete: PhaseValidationErrors; - policyName: string[]; -} - -export const validatePolicy = ( - saveAsNew: boolean, - policy: LegacyPolicy, - policies: PolicyFromES[], - originalPolicyName: string -): [boolean, ValidationErrors] => { - const policyNameErrors: string[] = []; - if (!policy.name) { - policyNameErrors.push(policyNameRequiredMessage); - } else { - if (policy.name.startsWith('_')) { - policyNameErrors.push(policyNameStartsWithUnderscoreErrorMessage); - } - if (policy.name.includes(',')) { - policyNameErrors.push(policyNameContainsCommaErrorMessage); - } - if (policy.name.includes(' ')) { - policyNameErrors.push(policyNameContainsSpaceErrorMessage); - } - if (window.TextEncoder && new window.TextEncoder().encode(policy.name).length > 255) { - policyNameErrors.push(policyNameTooLongErrorMessage); - } - - if (saveAsNew && policy.name === originalPolicyName) { - policyNameErrors.push(policyNameMustBeDifferentErrorMessage); - } else if (policy.name !== originalPolicyName) { - const policyNames = policies.map((existingPolicy) => existingPolicy.name); - if (policyNames.includes(policy.name)) { - policyNameErrors.push(policyNameAlreadyUsedErrorMessage); - } - } - } - - const deletePhaseErrors = validateDeletePhase(policy.phases.delete); - const isValid = policyNameErrors.length === 0 && Object.keys(deletePhaseErrors).length === 0; - return [ - isValid, - { - policyName: [...policyNameErrors], - delete: deletePhaseErrors, - }, - ]; -}; - -export const findFirstError = (errors?: ValidationErrors): string | undefined => { - if (!errors) { - return; - } - - if (errors.policyName.length > 0) { - return propertyof('policyName'); - } - - if (Object.keys(errors.delete).length > 0) { - return `${propertyof('delete')}.${Object.keys(errors.delete)[0]}`; - } -}; diff --git a/x-pack/plugins/index_lifecycle_management/public/shared_imports.ts b/x-pack/plugins/index_lifecycle_management/public/shared_imports.ts index 023aeba57aa7a..a5844af0bf6dd 100644 --- a/x-pack/plugins/index_lifecycle_management/public/shared_imports.ts +++ b/x-pack/plugins/index_lifecycle_management/public/shared_imports.ts @@ -18,6 +18,7 @@ export { getFieldValidityAndErrorMessage, useFormContext, FormSchema, + ValidationConfig, } from '../../../../src/plugins/es_ui_shared/static/forms/hook_form_lib'; export { fieldValidators } from '../../../../src/plugins/es_ui_shared/static/forms/helpers'; @@ -27,8 +28,12 @@ export { NumericField, SelectField, SuperSelectField, + ComboBoxField, + TextField, } from '../../../../src/plugins/es_ui_shared/static/forms/components'; +export { attemptToURIDecode } from '../../../../src/plugins/es_ui_shared/public'; + export { KibanaContextProvider } from '../../../../src/plugins/kibana_react/public'; export const useKibana = () => _useKibana(); diff --git a/x-pack/plugins/index_management/public/application/app_context.tsx b/x-pack/plugins/index_management/public/application/app_context.tsx index c654288aaceb8..5094aa2763a01 100644 --- a/x-pack/plugins/index_management/public/application/app_context.tsx +++ b/x-pack/plugins/index_management/public/application/app_context.tsx @@ -10,7 +10,7 @@ import { ManagementAppMountParams } from 'src/plugins/management/public'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/public'; import { CoreSetup, CoreStart } from '../../../../../src/core/public'; -import { IngestManagerSetup } from '../../../ingest_manager/public'; +import { IngestManagerSetup } from '../../../fleet/public'; import { IndexMgmtMetricsType } from '../types'; import { UiMetricService, NotificationService, HttpService } from './services'; import { ExtensionsService } from '../services'; diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_details/component_template_details.tsx b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_details/component_template_details.tsx index 6d9aa58d6c86b..2fb16874cf943 100644 --- a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_details/component_template_details.tsx +++ b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_details/component_template_details.tsx @@ -52,7 +52,7 @@ export const ComponentTemplateDetailsFlyoutContent: React.FunctionComponent { const { api } = useComponentTemplatesContext(); - const decodedComponentTemplateName = attemptToURIDecode(componentTemplateName); + const decodedComponentTemplateName = attemptToURIDecode(componentTemplateName)!; const { data: componentTemplateDetails, isLoading, error } = api.useLoadComponentTemplate( decodedComponentTemplateName diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/component_template_list.tsx b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/component_template_list.tsx index 00ea3ebf794ee..e8424ae46c6d2 100644 --- a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/component_template_list.tsx +++ b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/component_template_list.tsx @@ -84,7 +84,7 @@ export const ComponentTemplateList: React.FunctionComponent = ({ }), icon: 'pencil', handleActionClick: () => - goToEditComponentTemplate(attemptToURIDecode(componentTemplateName)), + goToEditComponentTemplate(attemptToURIDecode(componentTemplateName)!), }, { name: i18n.translate('xpack.idxMgmt.componentTemplateDetails.cloneActionLabel', { @@ -92,7 +92,7 @@ export const ComponentTemplateList: React.FunctionComponent = ({ }), icon: 'copy', handleActionClick: () => - goToCloneComponentTemplate(attemptToURIDecode(componentTemplateName)), + goToCloneComponentTemplate(attemptToURIDecode(componentTemplateName)!), }, { name: i18n.translate('xpack.idxMgmt.componentTemplateDetails.deleteButtonLabel', { @@ -103,7 +103,7 @@ export const ComponentTemplateList: React.FunctionComponent = ({ details._kbnMeta.usedBy.length > 0, closePopoverOnClick: true, handleActionClick: () => { - setComponentTemplatesToDelete([attemptToURIDecode(componentTemplateName)]); + setComponentTemplatesToDelete([attemptToURIDecode(componentTemplateName)!]); }, }, ]; diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_wizard/component_template_clone/component_template_clone.tsx b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_wizard/component_template_clone/component_template_clone.tsx index 6c03fcf5d9972..e6b403543f4b0 100644 --- a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_wizard/component_template_clone/component_template_clone.tsx +++ b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_wizard/component_template_clone/component_template_clone.tsx @@ -19,7 +19,7 @@ export interface Params { export const ComponentTemplateClone: FunctionComponent> = (props) => { const { sourceComponentTemplateName } = props.match.params; - const decodedSourceName = attemptToURIDecode(sourceComponentTemplateName); + const decodedSourceName = attemptToURIDecode(sourceComponentTemplateName)!; const { toasts, api } = useComponentTemplatesContext(); diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_wizard/component_template_edit/component_template_edit.tsx b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_wizard/component_template_edit/component_template_edit.tsx index 934f86f7d7590..500c84a97d222 100644 --- a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_wizard/component_template_edit/component_template_edit.tsx +++ b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_wizard/component_template_edit/component_template_edit.tsx @@ -31,7 +31,7 @@ export const ComponentTemplateEdit: React.FunctionComponent(false); const [saveError, setSaveError] = useState(null); - const decodedName = attemptToURIDecode(name); + const decodedName = attemptToURIDecode(name)!; const { error, data: componentTemplate, isLoading } = api.useLoadComponentTemplate(decodedName); diff --git a/x-pack/plugins/index_management/public/application/mount_management_section.ts b/x-pack/plugins/index_management/public/application/mount_management_section.ts index 52528d3c51145..c15af4f19827b 100644 --- a/x-pack/plugins/index_management/public/application/mount_management_section.ts +++ b/x-pack/plugins/index_management/public/application/mount_management_section.ts @@ -9,7 +9,7 @@ import { CoreSetup } from 'src/core/public'; import { ManagementAppMountParams } from 'src/plugins/management/public/'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/public'; -import { IngestManagerSetup } from '../../../ingest_manager/public'; +import { IngestManagerSetup } from '../../../fleet/public'; import { PLUGIN } from '../../common/constants'; import { ExtensionsService } from '../services'; import { IndexMgmtMetricsType, StartDependencies } from '../types'; diff --git a/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_list.tsx b/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_list.tsx index ba79319b566bf..20b93d9d71d04 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_list.tsx +++ b/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_list.tsx @@ -231,7 +231,7 @@ export const DataStreamList: React.FunctionComponent { history.push(`/${Section.DataStreams}`); diff --git a/x-pack/plugins/index_management/public/application/sections/home/template_list/template_list.tsx b/x-pack/plugins/index_management/public/application/sections/home/template_list/template_list.tsx index f3e82223c30e6..3689a875e28b2 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/template_list/template_list.tsx +++ b/x-pack/plugins/index_management/public/application/sections/home/template_list/template_list.tsx @@ -101,7 +101,7 @@ export const TemplateList: React.FunctionComponent { - const decodedTemplateName = attemptToURIDecode(name); + const decodedTemplateName = attemptToURIDecode(name)!; const isLegacy = getIsLegacyFromQueryParams(location); const [isSaving, setIsSaving] = useState(false); diff --git a/x-pack/plugins/index_management/public/application/sections/template_edit/template_edit.tsx b/x-pack/plugins/index_management/public/application/sections/template_edit/template_edit.tsx index 3e62f7f880f74..e3cb40b3a36e1 100644 --- a/x-pack/plugins/index_management/public/application/sections/template_edit/template_edit.tsx +++ b/x-pack/plugins/index_management/public/application/sections/template_edit/template_edit.tsx @@ -27,7 +27,7 @@ export const TemplateEdit: React.FunctionComponent { - const decodedTemplateName = attemptToURIDecode(name); + const decodedTemplateName = attemptToURIDecode(name)!; const isLegacy = getIsLegacyFromQueryParams(location); const [isSaving, setIsSaving] = useState(false); diff --git a/x-pack/plugins/index_management/public/types.ts b/x-pack/plugins/index_management/public/types.ts index f860b89b0ba0c..34d060d935415 100644 --- a/x-pack/plugins/index_management/public/types.ts +++ b/x-pack/plugins/index_management/public/types.ts @@ -5,7 +5,7 @@ */ import { ExtensionsSetup } from './services'; -import { IngestManagerSetup } from '../../ingest_manager/public'; +import { IngestManagerSetup } from '../../fleet/public'; import { UsageCollectionSetup } from '../../../../src/plugins/usage_collection/public'; import { ManagementSetup } from '../../../../src/plugins/management/public'; import { SharePluginStart } from '../../../../src/plugins/share/public'; diff --git a/x-pack/plugins/infra/public/containers/logs/log_entries/index.ts b/x-pack/plugins/infra/public/containers/logs/log_entries/index.ts index 4c8c610794b2e..214bb16b24283 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_entries/index.ts +++ b/x-pack/plugins/infra/public/containers/logs/log_entries/index.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import { useEffect, useState, useReducer, useCallback } from 'react'; +import { useMountedState } from 'react-use'; import createContainer from 'constate'; import { pick, throttle } from 'lodash'; import { TimeKey, timeKeyIsBetween } from '../../../../common/time'; @@ -146,15 +147,20 @@ const useFetchEntriesEffect = ( props: LogEntriesProps ) => { const { services } = useKibanaContextForPlugin(); + const isMounted = useMountedState(); const [prevParams, cachePrevParams] = useState(); const [startedStreaming, setStartedStreaming] = useState(false); + const dispatchIfMounted = useCallback((action) => (isMounted() ? dispatch(action) : undefined), [ + dispatch, + isMounted, + ]); const runFetchNewEntriesRequest = async (overrides: Partial = {}) => { if (!props.startTimestamp || !props.endTimestamp) { return; } - dispatch({ type: Action.FetchingNewEntries }); + dispatchIfMounted({ type: Action.FetchingNewEntries }); try { const commonFetchArgs: LogEntriesBaseRequest = { @@ -175,13 +181,15 @@ const useFetchEntriesEffect = ( }; const { data: payload } = await fetchLogEntries(fetchArgs, services.http.fetch); - dispatch({ type: Action.ReceiveNewEntries, payload }); + dispatchIfMounted({ type: Action.ReceiveNewEntries, payload }); // Move position to the bottom if it's the first load. // Do it in the next tick to allow the `dispatch` to fire if (!props.timeKey && payload.bottomCursor) { setTimeout(() => { - props.jumpToTargetPosition(payload.bottomCursor!); + if (isMounted()) { + props.jumpToTargetPosition(payload.bottomCursor!); + } }); } else if ( props.timeKey && @@ -192,7 +200,7 @@ const useFetchEntriesEffect = ( props.jumpToTargetPosition(payload.topCursor); } } catch (e) { - dispatch({ type: Action.ErrorOnNewEntries }); + dispatchIfMounted({ type: Action.ErrorOnNewEntries }); } }; @@ -210,7 +218,7 @@ const useFetchEntriesEffect = ( return; } - dispatch({ type: Action.FetchingMoreEntries }); + dispatchIfMounted({ type: Action.FetchingMoreEntries }); try { const commonFetchArgs: LogEntriesBaseRequest = { @@ -232,14 +240,14 @@ const useFetchEntriesEffect = ( const { data: payload } = await fetchLogEntries(fetchArgs, services.http.fetch); - dispatch({ + dispatchIfMounted({ type: getEntriesBefore ? Action.ReceiveEntriesBefore : Action.ReceiveEntriesAfter, payload, }); return payload.bottomCursor; } catch (e) { - dispatch({ type: Action.ErrorOnMoreEntries }); + dispatchIfMounted({ type: Action.ErrorOnMoreEntries }); } }; @@ -322,7 +330,7 @@ const useFetchEntriesEffect = ( after: props.endTimestamp > prevParams.endTimestamp, }; - dispatch({ type: Action.ExpandRange, payload: shouldExpand }); + dispatchIfMounted({ type: Action.ExpandRange, payload: shouldExpand }); }; const expandRangeEffectDependencies = [ diff --git a/x-pack/plugins/infra/public/utils/use_tracked_promise.ts b/x-pack/plugins/infra/public/utils/use_tracked_promise.ts index 9951b62fa64a3..42518127f68bf 100644 --- a/x-pack/plugins/infra/public/utils/use_tracked_promise.ts +++ b/x-pack/plugins/infra/public/utils/use_tracked_promise.ts @@ -6,13 +6,15 @@ /* eslint-disable max-classes-per-file */ -import { DependencyList, useEffect, useMemo, useRef, useState } from 'react'; +import { DependencyList, useEffect, useMemo, useRef, useState, useCallback } from 'react'; +import { useMountedState } from 'react-use'; interface UseTrackedPromiseArgs { createPromise: (...args: Arguments) => Promise; onResolve?: (result: Result) => void; onReject?: (value: unknown) => void; cancelPreviousOn?: 'creation' | 'settlement' | 'resolution' | 'rejection' | 'never'; + triggerOrThrow?: 'always' | 'whenMounted'; } /** @@ -64,6 +66,16 @@ interface UseTrackedPromiseArgs { * The last argument is a normal React hook dependency list that indicates * under which conditions a new reference to the configuration object should be * used. + * + * The `onResolve`, `onReject` and possible uncatched errors are only triggered + * if the underlying component is mounted. To ensure they always trigger (i.e. + * if the promise is called in a `useLayoutEffect`) use the `triggerOrThrow` + * attribute: + * + * 'whenMounted': (default) they are called only if the component is mounted. + * + * 'always': they always call. The consumer is then responsible of ensuring no + * side effects happen if the underlying component is not mounted. */ export const useTrackedPromise = ( { @@ -71,9 +83,20 @@ export const useTrackedPromise = ( onResolve = noOp, onReject = noOp, cancelPreviousOn = 'never', + triggerOrThrow = 'whenMounted', }: UseTrackedPromiseArgs, dependencies: DependencyList ) => { + const isComponentMounted = useMountedState(); + const shouldTriggerOrThrow = useCallback(() => { + switch (triggerOrThrow) { + case 'always': + return true; + case 'whenMounted': + return isComponentMounted(); + } + }, [isComponentMounted, triggerOrThrow]); + /** * If a promise is currently pending, this holds a reference to it and its * cancellation function. @@ -144,7 +167,7 @@ export const useTrackedPromise = ( (pendingPromise) => pendingPromise.promise !== newPendingPromise.promise ); - if (onResolve) { + if (onResolve && shouldTriggerOrThrow()) { onResolve(value); } @@ -173,11 +196,13 @@ export const useTrackedPromise = ( (pendingPromise) => pendingPromise.promise !== newPendingPromise.promise ); - if (onReject) { - onReject(value); - } + if (shouldTriggerOrThrow()) { + if (onReject) { + onReject(value); + } - throw value; + throw value; + } } ), }; diff --git a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_clone/pipelines_clone.tsx b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_clone/pipelines_clone.tsx index 9465117b6b589..df60907973156 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_clone/pipelines_clone.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_clone/pipelines_clone.tsx @@ -25,7 +25,7 @@ export const PipelinesClone: FunctionComponent> const { sourceName } = props.match.params; const { services } = useKibana(); - const decodedSourceName = attemptToURIDecode(sourceName); + const decodedSourceName = attemptToURIDecode(sourceName)!; const { error, data: pipeline, isLoading, isInitialRequest } = services.api.useLoadPipeline( decodedSourceName ); diff --git a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_edit/pipelines_edit.tsx b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_edit/pipelines_edit.tsx index 7e2e85ab23fb3..2b53fdb6a6375 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_edit/pipelines_edit.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_edit/pipelines_edit.tsx @@ -38,7 +38,7 @@ export const PipelinesEdit: React.FunctionComponent(false); const [saveError, setSaveError] = useState(null); - const decodedPipelineName = attemptToURIDecode(name); + const decodedPipelineName = attemptToURIDecode(name)!; const { error, data: pipeline, isLoading } = services.api.useLoadPipeline(decodedPipelineName); diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx index c9d99bcfb6d8d..0332f11aa78b3 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx @@ -451,6 +451,7 @@ export function LayerPanel( columnId: activeId, filterOperations: activeGroup.filterOperations, suggestedPriority: activeGroup?.suggestedPriority, + dimensionGroups: groups, setState: (newState: unknown) => { props.updateAll( datasourceId, diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.test.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.test.tsx index f7a6f0597bf9c..b3ea14efbae80 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.test.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.test.tsx @@ -601,7 +601,8 @@ describe('editor_frame', () => { setDatasourceState(updatedState); }); - expect(mockVisualization.getConfiguration).toHaveBeenCalledTimes(2); + // validation requires to calls this getConfiguration API + expect(mockVisualization.getConfiguration).toHaveBeenCalledTimes(6); expect(mockVisualization.getConfiguration).toHaveBeenLastCalledWith( expect.objectContaining({ state: updatedState, @@ -680,7 +681,8 @@ describe('editor_frame', () => { setDatasourceState({}); }); - expect(mockVisualization.getConfiguration).toHaveBeenCalledTimes(2); + // validation requires to calls this getConfiguration API + expect(mockVisualization.getConfiguration).toHaveBeenCalledTimes(6); expect(mockVisualization.getConfiguration).toHaveBeenLastCalledWith( expect.objectContaining({ frame: expect.objectContaining({ @@ -1193,7 +1195,8 @@ describe('editor_frame', () => { instance.find('[data-test-subj="lnsSuggestion"]').at(2).simulate('click'); }); - expect(mockVisualization.getConfiguration).toHaveBeenCalledTimes(1); + // validation requires to calls this getConfiguration API + expect(mockVisualization.getConfiguration).toHaveBeenCalledTimes(4); expect(mockVisualization.getConfiguration).toHaveBeenCalledWith( expect.objectContaining({ state: suggestionVisState, diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_helpers.ts b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_helpers.ts index 28ad6c531e255..647c0f3ac9cca 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_helpers.ts +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_helpers.ts @@ -6,7 +6,13 @@ import { SavedObjectReference } from 'kibana/public'; import { Ast } from '@kbn/interpreter/common'; -import { Datasource, DatasourcePublicAPI, FramePublicAPI, Visualization } from '../../types'; +import { + Datasource, + DatasourcePublicAPI, + FramePublicAPI, + Visualization, + VisualizationDimensionGroupConfig, +} from '../../types'; import { buildExpression } from './expression_helpers'; import { Document } from '../../persistence/saved_object_store'; import { VisualizeFieldContext } from '../../../../../../src/plugins/ui_actions/public'; @@ -104,8 +110,24 @@ export const validateDatasourceAndVisualization = ( longMessage: string; }> | undefined => { + const layersGroups = + currentVisualizationState && + currentVisualization + ?.getLayerIds(currentVisualizationState) + .reduce>((memo, layerId) => { + const groups = currentVisualization?.getConfiguration({ + frame: frameAPI, + layerId, + state: currentVisualizationState, + }).groups; + if (groups) { + memo[layerId] = groups; + } + return memo; + }, {}); + const datasourceValidationErrors = currentDatasourceState - ? currentDataSource?.getErrorMessages(currentDatasourceState) + ? currentDataSource?.getErrorMessages(currentDatasourceState, layersGroups) : undefined; const visualizationValidationErrors = currentVisualizationState diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx index 2e24b64ecca26..97165a8513078 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx @@ -23,7 +23,7 @@ import { IconType } from '@elastic/eui/src/components/icon/icon'; import { Ast, toExpression } from '@kbn/interpreter/common'; import { i18n } from '@kbn/i18n'; import classNames from 'classnames'; -import { ExecutionContextSearch } from 'src/plugins/expressions'; +import { DataPublicPluginStart, ExecutionContextSearch } from 'src/plugins/data/public'; import { Action, PreviewState } from './state_management'; import { Datasource, Visualization, FramePublicAPI, DatasourcePublicAPI } from '../../types'; import { getSuggestions, switchToSuggestion } from './suggestion_helpers'; @@ -33,7 +33,6 @@ import { } from '../../../../../../src/plugins/expressions/public'; import { prependDatasourceExpression } from './expression_helpers'; import { trackUiEvent, trackSuggestionEvent } from '../../lens_ui_telemetry'; -import { DataPublicPluginStart } from '../../../../../../src/plugins/data/public'; import { validateDatasourceAndVisualization } from './state_helpers'; const MAX_SUGGESTIONS_DISPLAYED = 5; diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.tsx index e0dd3b3fe01ae..00cb932a6d4e2 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.tsx @@ -20,7 +20,11 @@ import { EuiTitle, } from '@elastic/eui'; import { CoreStart, CoreSetup } from 'kibana/public'; -import { ExecutionContextSearch } from 'src/plugins/expressions'; +import { + DataPublicPluginStart, + ExecutionContextSearch, + TimefilterContract, +} from 'src/plugins/data/public'; import { ExpressionRendererEvent, ExpressionRenderError, @@ -44,10 +48,6 @@ import { VisualizeFieldContext, } from '../../../../../../../src/plugins/ui_actions/public'; import { VIS_EVENT_TO_TRIGGER } from '../../../../../../../src/plugins/visualizations/public'; -import { - DataPublicPluginStart, - TimefilterContract, -} from '../../../../../../../src/plugins/data/public'; import { WorkspacePanelWrapper } from './workspace_panel_wrapper'; import { DropIllustration } from '../../../assets/drop_illustration'; import { LensInspectorAdapters } from '../../types'; diff --git a/x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable.tsx b/x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable.tsx index 33e5dee99081f..8139631daa971 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable.tsx @@ -8,6 +8,7 @@ import _ from 'lodash'; import React from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; import { + ExecutionContextSearch, Filter, IIndexPattern, Query, @@ -15,7 +16,6 @@ import { TimeRange, IndexPattern, } from 'src/plugins/data/public'; -import { ExecutionContextSearch } from 'src/plugins/expressions'; import { PaletteOutput } from 'src/plugins/charts/public'; import { Subscription } from 'rxjs'; diff --git a/x-pack/plugins/lens/public/editor_frame_service/embeddable/expression_wrapper.tsx b/x-pack/plugins/lens/public/editor_frame_service/embeddable/expression_wrapper.tsx index 7479577805bdd..4a3ba971381fb 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/embeddable/expression_wrapper.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/embeddable/expression_wrapper.tsx @@ -12,7 +12,7 @@ import { ExpressionRendererEvent, ReactExpressionRendererType, } from 'src/plugins/expressions/public'; -import { ExecutionContextSearch } from 'src/plugins/expressions'; +import { ExecutionContextSearch } from 'src/plugins/data/public'; import { getOriginalRequestErrorMessage } from '../error_helper'; export interface ExpressionWrapperProps { diff --git a/x-pack/plugins/lens/public/editor_frame_service/merge_tables.test.ts b/x-pack/plugins/lens/public/editor_frame_service/merge_tables.test.ts index 07c16665d11b4..02c07d809e09f 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/merge_tables.test.ts +++ b/x-pack/plugins/lens/public/editor_frame_service/merge_tables.test.ts @@ -6,6 +6,7 @@ import moment from 'moment'; import { mergeTables } from './merge_tables'; +import { ExpressionValueSearchContext } from 'src/plugins/data/public'; import { Datatable, ExecutionContext } from 'src/plugins/expressions'; import { LensInspectorAdapters } from './types'; @@ -52,7 +53,7 @@ describe('lens_merge_tables', () => { const adapters: LensInspectorAdapters = { tables: {} }; mergeTables.fn(null, { layerIds: ['first', 'second'], tables: [sampleTable1, sampleTable2] }, { inspectorAdapters: adapters, - } as ExecutionContext); + } as ExecutionContext); expect(adapters.tables!.first).toBe(sampleTable1); expect(adapters.tables!.second).toBe(sampleTable2); }); diff --git a/x-pack/plugins/lens/public/editor_frame_service/merge_tables.ts b/x-pack/plugins/lens/public/editor_frame_service/merge_tables.ts index 03ef7cf9cc637..109b30144fc20 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/merge_tables.ts +++ b/x-pack/plugins/lens/public/editor_frame_service/merge_tables.ts @@ -9,9 +9,8 @@ import { ExecutionContext, Datatable, ExpressionFunctionDefinition, - ExpressionValueSearchContext, } from 'src/plugins/expressions/public'; -import { search } from '../../../../../src/plugins/data/public'; +import { ExpressionValueSearchContext, search } from '../../../../../src/plugins/data/public'; const { toAbsoluteDates } = search.aggs; import { LensMultiTable } from '../types'; @@ -27,7 +26,7 @@ export const mergeTables: ExpressionFunctionDefinition< ExpressionValueSearchContext | null, MergeTables, LensMultiTable, - ExecutionContext + ExecutionContext > = { name: 'lens_merge_tables', type: 'lens_multitable', diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.test.tsx index 4ff57450edbb3..3ed04b08df58f 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.test.tsx @@ -178,6 +178,7 @@ describe('IndexPatternDimensionEditorPanel', () => { } as unknown) as DataPublicPluginStart['fieldFormats'], } as unknown) as DataPublicPluginStart, core: {} as CoreSetup, + dimensionGroups: [], }; jest.clearAllMocks(); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable.test.ts b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable.test.ts index 89175ee442d22..1d85c1f8f78ca 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable.test.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable.test.ts @@ -150,6 +150,7 @@ describe('IndexPatternDimensionEditorPanel', () => { } as unknown) as DataPublicPluginStart['fieldFormats'], } as unknown) as DataPublicPluginStart, core: {} as CoreSetup, + dimensionGroups: [], }; jest.clearAllMocks(); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.tsx index ecca1b878e9a7..fa106e90d518a 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.tsx @@ -343,7 +343,7 @@ export function getIndexPatternDatasource({ getDatasourceSuggestionsFromCurrentState, getDatasourceSuggestionsForVisualizeField, - getErrorMessages(state) { + getErrorMessages(state, layersGroups) { if (!state) { return; } diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/ranges.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/ranges.test.tsx index a263194843986..ce015284e544b 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/ranges.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/ranges.test.tsx @@ -748,6 +748,36 @@ describe('ranges', () => { /^Bytes format:/ ); }); + + it('should not reset formatters when switching between custom ranges and auto histogram', () => { + const setStateSpy = jest.fn(); + // now set a format on the range operation + (state.layers.first.columns.col1 as RangeIndexPatternColumn).params.format = { + id: 'custom', + params: { decimals: 3 }, + }; + + const instance = mount( + + ); + + // This series of act closures are made to make it work properly the update flush + act(() => { + instance.find(EuiLink).first().prop('onClick')!({} as ReactMouseEvent); + }); + + expect(setStateSpy.mock.calls[1][0].layers.first.columns.col1.params.format).toEqual({ + id: 'custom', + params: { decimals: 3 }, + }); + }); }); }); }); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/ranges.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/ranges.tsx index 86aa6b75cf648..c6cc6ae13f178 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/ranges.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/ranges.tsx @@ -223,7 +223,7 @@ export const rangeOperation: OperationDefinition diff --git a/x-pack/plugins/lens/public/shared_components/toolbar_popover.tsx b/x-pack/plugins/lens/public/shared_components/toolbar_popover.tsx index 20837424dc7b5..cf2268c6eadf2 100644 --- a/x-pack/plugins/lens/public/shared_components/toolbar_popover.tsx +++ b/x-pack/plugins/lens/public/shared_components/toolbar_popover.tsx @@ -11,6 +11,7 @@ import { EuiIconLegend } from '../assets/legend'; const typeToIconMap: { [type: string]: string | IconType } = { legend: EuiIconLegend as IconType, + labels: 'visText', values: 'number', }; diff --git a/x-pack/plugins/lens/public/types.ts b/x-pack/plugins/lens/public/types.ts index 3c96579fdc943..4ad849c5d441e 100644 --- a/x-pack/plugins/lens/public/types.ts +++ b/x-pack/plugins/lens/public/types.ts @@ -184,7 +184,10 @@ export interface Datasource { ) => Array>; getPublicAPI: (props: PublicAPIProps) => DatasourcePublicAPI; - getErrorMessages: (state: T) => Array<{ shortMessage: string; longMessage: string }> | undefined; + getErrorMessages: ( + state: T, + layersGroups?: Record + ) => Array<{ shortMessage: string; longMessage: string }> | undefined; /** * uniqueLabels of dimensions exposed for aria-labels of dragged dimensions */ @@ -242,6 +245,7 @@ export type DatasourceDimensionEditorProps = DatasourceDimensionPro setState: StateSetter; core: Pick; dateRange: DateRange; + dimensionGroups: VisualizationDimensionGroupConfig[]; }; export type DatasourceDimensionTriggerProps = DatasourceDimensionProps & { diff --git a/x-pack/plugins/lens/public/xy_visualization/expression.tsx b/x-pack/plugins/lens/public/xy_visualization/expression.tsx index d238e052a7c7f..730f8508e2889 100644 --- a/x-pack/plugins/lens/public/xy_visualization/expression.tsx +++ b/x-pack/plugins/lens/public/xy_visualization/expression.tsx @@ -29,7 +29,6 @@ import { I18nProvider } from '@kbn/i18n/react'; import { ExpressionFunctionDefinition, ExpressionRenderDefinition, - ExpressionValueSearchContext, Datatable, DatatableRow, } from 'src/plugins/expressions/public'; @@ -45,7 +44,7 @@ import { import { XYArgs, SeriesType, visualizationTypes } from './types'; import { VisualizationContainer } from '../visualization_container'; import { isHorizontalChart, getSeriesColor } from './state_helpers'; -import { parseInterval } from '../../../../../src/plugins/data/common'; +import { ExpressionValueSearchContext, search } from '../../../../../src/plugins/data/public'; import { ChartsPluginSetup, PaletteRegistry, @@ -384,7 +383,8 @@ export function XYChart({ // add minInterval only for single point in domain if (data.dateRange && isSingleTimestampInXDomain()) { const params = xAxisColumn?.meta?.sourceParams?.params as Record; - if (params?.interval !== 'auto') return parseInterval(params?.interval)?.asMilliseconds(); + if (params?.interval !== 'auto') + return search.aggs.parseInterval(params?.interval)?.asMilliseconds(); const { fromDate, toDate } = data.dateRange; const duration = moment(toDate).diff(moment(fromDate)); diff --git a/x-pack/plugins/ml/public/application/components/anomalies_table/anomaly_details.js b/x-pack/plugins/ml/public/application/components/anomalies_table/anomaly_details.js index a2a3aea5988aa..fdd855e80a6df 100644 --- a/x-pack/plugins/ml/public/application/components/anomalies_table/anomaly_details.js +++ b/x-pack/plugins/ml/public/application/components/anomalies_table/anomaly_details.js @@ -38,6 +38,7 @@ import { import { MULTI_BUCKET_IMPACT } from '../../../../common/constants/multi_bucket_impact'; import { formatValue } from '../../formatters/format_value'; import { MAX_CHARS } from './anomalies_table_constants'; +import { ML_JOB_AGGREGATION } from '../../../../common/constants/aggregation_types'; const TIME_FIELD_NAME = 'timestamp'; @@ -130,7 +131,8 @@ function getDetailsItems(anomaly, examples, filter) { title: i18n.translate('xpack.ml.anomaliesTable.anomalyDetails.functionTitle', { defaultMessage: 'function', }), - description: source.function !== 'metric' ? source.function : source.function_description, + description: + source.function !== ML_JOB_AGGREGATION.METRIC ? source.function : source.function_description, }); if (source.field_name !== undefined) { diff --git a/x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_chart_config_builder.js b/x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_chart_config_builder.js index b75784c95c520..2ba6e38081e6e 100644 --- a/x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_chart_config_builder.js +++ b/x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_chart_config_builder.js @@ -13,6 +13,8 @@ import { parseInterval } from '../../../../common/util/parse_interval'; import { getEntityFieldList } from '../../../../common/util/anomaly_utils'; import { buildConfigFromDetector } from '../../util/chart_config_builder'; import { mlJobService } from '../../services/job_service'; +import { mlFunctionToESAggregation } from '../../../../common/util/job_utils'; +import { ML_JOB_AGGREGATION } from '../../../../common/constants/aggregation_types'; // Builds the chart configuration for the provided anomaly record, returning // an object with properties used for the display (series function and field, aggregation interval etc), @@ -48,6 +50,10 @@ export function buildConfig(record) { // define the metric series to be plotted. config.entityFields = getEntityFieldList(record); + if (record.function === ML_JOB_AGGREGATION.METRIC) { + config.metricFunction = mlFunctionToESAggregation(record.function_description); + } + // Build the tooltip data for the chart info icon, showing further details on what is being plotted. let functionLabel = config.metricFunction; if (config.metricFieldName !== undefined) { diff --git a/x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_charts_container_service.js b/x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_charts_container_service.js index b9634f0eac359..39166841a4e1b 100644 --- a/x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_charts_container_service.js +++ b/x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_charts_container_service.js @@ -46,8 +46,6 @@ const ML_TIME_FIELD_NAME = 'timestamp'; const USE_OVERALL_CHART_LIMITS = false; const MAX_CHARTS_PER_ROW = 4; -// callback(getDefaultChartsData()); - export const anomalyDataChange = function ( chartsContainerWidth, anomalyRecords, diff --git a/x-pack/plugins/ml/public/application/routing/routes/timeseriesexplorer.tsx b/x-pack/plugins/ml/public/application/routing/routes/timeseriesexplorer.tsx index e4cf43ac91727..9331fdc04b7bb 100644 --- a/x-pack/plugins/ml/public/application/routing/routes/timeseriesexplorer.tsx +++ b/x-pack/plugins/ml/public/application/routing/routes/timeseriesexplorer.tsx @@ -38,6 +38,7 @@ import { useResolver } from '../use_resolver'; import { basicResolvers } from '../resolvers'; import { getBreadcrumbWithUrlForApp } from '../breadcrumbs'; import { useTimefilter } from '../../contexts/kibana'; +import { useToastNotificationService } from '../../services/toast_notification_service'; export const timeSeriesExplorerRouteFactory = ( navigateToPath: NavigateToPath, @@ -88,6 +89,7 @@ export const TimeSeriesExplorerUrlStateManager: FC { + const toastNotificationService = useToastNotificationService(); const [appState, setAppState] = useUrlState('_a'); const [globalState, setGlobalState] = useUrlState('_g'); const [lastRefresh, setLastRefresh] = useState(0); @@ -293,6 +295,7 @@ export const TimeSeriesExplorerUrlStateManager: FC ({ latestMs: number, dateFormatTz: string, maxRecords: number, - maxExamples: number, - influencersFilterQuery: any + maxExamples?: number, + influencersFilterQuery?: any, + functionDescription?: string ) { const body = JSON.stringify({ jobIds, @@ -39,6 +40,7 @@ export const resultsApiProvider = (httpService: HttpService) => ({ maxRecords, maxExamples, influencersFilterQuery, + functionDescription, }); return httpService.http$({ diff --git a/x-pack/plugins/ml/public/application/services/results_service/result_service_rx.ts b/x-pack/plugins/ml/public/application/services/results_service/result_service_rx.ts index 7c2c28fe9385c..2869a7439614f 100644 --- a/x-pack/plugins/ml/public/application/services/results_service/result_service_rx.ts +++ b/x-pack/plugins/ml/public/application/services/results_service/result_service_rx.ts @@ -19,6 +19,7 @@ import { ML_MEDIAN_PERCENTS } from '../../../../common/util/job_utils'; import { JobId } from '../../../../common/types/anomaly_detection_jobs'; import { MlApiServices } from '../ml_api_service'; import { CriteriaField } from './index'; +import { aggregationTypeTransform } from '../../../../common/util/anomaly_utils'; interface ResultResponse { success: boolean; @@ -347,9 +348,10 @@ export function resultsServiceRxProvider(mlApiServices: MlApiServices) { jobIds: string[], criteriaFields: CriteriaField[], threshold: any, - earliestMs: number, - latestMs: number, - maxResults: number | undefined + earliestMs: number | null, + latestMs: number | null, + maxResults: number | undefined, + functionDescription?: string ): Observable { const obj: RecordsForCriteria = { success: true, records: [] }; @@ -400,6 +402,19 @@ export function resultsServiceRxProvider(mlApiServices: MlApiServices) { }); }); + if (functionDescription !== undefined) { + const mlFunctionToPlotIfMetric = + functionDescription !== undefined + ? aggregationTypeTransform.toML(functionDescription) + : functionDescription; + + boolCriteria.push({ + term: { + function_description: mlFunctionToPlotIfMetric, + }, + }); + } + return mlApiServices.results .anomalySearch$( { diff --git a/x-pack/plugins/ml/public/application/services/results_service/results_service.d.ts b/x-pack/plugins/ml/public/application/services/results_service/results_service.d.ts index aae0cb51aa81d..962f384cf5b1b 100644 --- a/x-pack/plugins/ml/public/application/services/results_service/results_service.d.ts +++ b/x-pack/plugins/ml/public/application/services/results_service/results_service.d.ts @@ -76,6 +76,7 @@ export function resultsServiceProvider( criteriaFields: any[], earliestMs: number, latestMs: number, - intervalMs: number + intervalMs: number, + actualPlotFunctionIfMetric?: string ): Promise; }; diff --git a/x-pack/plugins/ml/public/application/services/results_service/results_service.js b/x-pack/plugins/ml/public/application/services/results_service/results_service.js index 14a725c2e22b7..d053d69b4d1f2 100644 --- a/x-pack/plugins/ml/public/application/services/results_service/results_service.js +++ b/x-pack/plugins/ml/public/application/services/results_service/results_service.js @@ -12,6 +12,7 @@ import { ANOMALY_SWIM_LANE_HARD_LIMIT, SWIM_LANE_DEFAULT_PAGE_SIZE, } from '../../explorer/explorer_constants'; +import { aggregationTypeTransform } from '../../../../common/util/anomaly_utils'; /** * Service for carrying out Elasticsearch queries to obtain data for the Ml Results dashboards. @@ -1293,7 +1294,14 @@ export function resultsServiceProvider(mlApiServices) { // criteria, time range, and aggregation interval. // criteriaFields parameter must be an array, with each object in the array having 'fieldName' // 'fieldValue' properties. - getRecordMaxScoreByTime(jobId, criteriaFields, earliestMs, latestMs, intervalMs) { + getRecordMaxScoreByTime( + jobId, + criteriaFields, + earliestMs, + latestMs, + intervalMs, + actualPlotFunctionIfMetric + ) { return new Promise((resolve, reject) => { const obj = { success: true, @@ -1321,7 +1329,18 @@ export function resultsServiceProvider(mlApiServices) { }, }); }); + if (actualPlotFunctionIfMetric !== undefined) { + const mlFunctionToPlotIfMetric = + actualPlotFunctionIfMetric !== undefined + ? aggregationTypeTransform.toML(actualPlotFunctionIfMetric) + : actualPlotFunctionIfMetric; + mustCriteria.push({ + term: { + function_description: mlFunctionToPlotIfMetric, + }, + }); + } mlApiServices.results .anomalySearch( { diff --git a/x-pack/plugins/ml/public/application/timeseriesexplorer/components/plot_function_controls/index.ts b/x-pack/plugins/ml/public/application/timeseriesexplorer/components/plot_function_controls/index.ts new file mode 100644 index 0000000000000..b8247eb91e1f5 --- /dev/null +++ b/x-pack/plugins/ml/public/application/timeseriesexplorer/components/plot_function_controls/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { PlotByFunctionControls } from './plot_function_controls'; diff --git a/x-pack/plugins/ml/public/application/timeseriesexplorer/components/plot_function_controls/plot_function_controls.tsx b/x-pack/plugins/ml/public/application/timeseriesexplorer/components/plot_function_controls/plot_function_controls.tsx new file mode 100644 index 0000000000000..0356c20fecb9a --- /dev/null +++ b/x-pack/plugins/ml/public/application/timeseriesexplorer/components/plot_function_controls/plot_function_controls.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; + * you may not use this file except in compliance with the Elastic License. + */ +import React from 'react'; +import { EuiFlexItem, EuiFormRow, EuiSelect } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +const plotByFunctionOptions = [ + { + value: 'mean', + text: i18n.translate('xpack.ml.timeSeriesExplorer.plotByAvgOptionLabel', { + defaultMessage: 'mean', + }), + }, + { + value: 'min', + text: i18n.translate('xpack.ml.timeSeriesExplorer.plotByMinOptionLabel', { + defaultMessage: 'min', + }), + }, + { + value: 'max', + text: i18n.translate('xpack.ml.timeSeriesExplorer.plotByMaxOptionLabel', { + defaultMessage: 'max', + }), + }, +]; +export const PlotByFunctionControls = ({ + functionDescription, + setFunctionDescription, +}: { + functionDescription: undefined | string; + setFunctionDescription: (func: string) => void; +}) => { + if (functionDescription === undefined) return null; + return ( + + + setFunctionDescription(e.target.value)} + aria-label={i18n.translate('xpack.ml.timeSeriesExplorer.metricPlotByOptionLabel', { + defaultMessage: 'Pick function to plot by (min, max, or average) if metric function', + })} + /> + + + ); +}; diff --git a/x-pack/plugins/ml/public/application/timeseriesexplorer/components/timeseries_chart/timeseries_chart.js b/x-pack/plugins/ml/public/application/timeseriesexplorer/components/timeseries_chart/timeseries_chart.js index 3169ecfd1bbc7..8df186c5c3c6e 100644 --- a/x-pack/plugins/ml/public/application/timeseriesexplorer/components/timeseries_chart/timeseries_chart.js +++ b/x-pack/plugins/ml/public/application/timeseriesexplorer/components/timeseries_chart/timeseries_chart.js @@ -1475,6 +1475,22 @@ class TimeseriesChartIntl extends Component { }); } + if (marker.metricFunction) { + tooltipData.push({ + label: i18n.translate( + 'xpack.ml.timeSeriesExplorer.timeSeriesChart.metricActualPlotFunctionLabel', + { + defaultMessage: 'function', + } + ), + value: marker.metricFunction, + seriesIdentifier: { + key: seriesKey, + }, + valueAccessor: 'metric_function', + }); + } + if (modelPlotEnabled === false) { // Show actual/typical when available except for rare detectors. // Rare detectors always have 1 as actual and the probability as typical. diff --git a/x-pack/plugins/ml/public/application/timeseriesexplorer/get_criteria_fields.ts b/x-pack/plugins/ml/public/application/timeseriesexplorer/get_criteria_fields.ts new file mode 100644 index 0000000000000..f9775976206c2 --- /dev/null +++ b/x-pack/plugins/ml/public/application/timeseriesexplorer/get_criteria_fields.ts @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +/** + * Updates criteria fields for API calls, e.g. getAnomaliesTableData + * @param detectorIndex + * @param entities + */ +export const getCriteriaFields = (detectorIndex: number, entities: Record) => { + // Only filter on the entity if the field has a value. + const nonBlankEntities = entities.filter( + (entity: { fieldValue: any }) => entity.fieldValue !== null + ); + return [ + { + fieldName: 'detector_index', + fieldValue: detectorIndex, + }, + ...nonBlankEntities, + ]; +}; diff --git a/x-pack/plugins/ml/public/application/timeseriesexplorer/get_function_description.ts b/x-pack/plugins/ml/public/application/timeseriesexplorer/get_function_description.ts new file mode 100644 index 0000000000000..029e4645cfe26 --- /dev/null +++ b/x-pack/plugins/ml/public/application/timeseriesexplorer/get_function_description.ts @@ -0,0 +1,62 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { i18n } from '@kbn/i18n'; +import { mlResultsService } from '../services/results_service'; +import { ToastNotificationService } from '../services/toast_notification_service'; +import { getControlsForDetector } from './get_controls_for_detector'; +import { getCriteriaFields } from './get_criteria_fields'; +import { CombinedJob } from '../../../common/types/anomaly_detection_jobs'; +import { ML_JOB_AGGREGATION } from '../../../common/constants/aggregation_types'; + +/** + * Get the function description from the record with the highest anomaly score + */ +export const getFunctionDescription = async ( + { + selectedDetectorIndex, + selectedEntities, + selectedJobId, + selectedJob, + }: { + selectedDetectorIndex: number; + selectedEntities: Record; + selectedJobId: string; + selectedJob: CombinedJob; + }, + toastNotificationService: ToastNotificationService +) => { + // if the detector's function is metric, fetch the highest scoring anomaly record + // and set to plot the function_description (avg/min/max) of that record by default + if ( + selectedJob?.analysis_config?.detectors[selectedDetectorIndex]?.function !== + ML_JOB_AGGREGATION.METRIC + ) + return; + + const entityControls = getControlsForDetector( + selectedDetectorIndex, + selectedEntities, + selectedJobId + ); + const criteriaFields = getCriteriaFields(selectedDetectorIndex, entityControls); + try { + const resp = await mlResultsService + .getRecordsForCriteria([selectedJob.job_id], criteriaFields, 0, null, null, 1) + .toPromise(); + if (Array.isArray(resp?.records) && resp.records.length === 1) { + const highestScoringAnomaly = resp.records[0]; + return highestScoringAnomaly?.function_description; + } + } catch (error) { + toastNotificationService.displayErrorToast( + error, + i18n.translate('xpack.ml.timeSeriesExplorer.highestAnomalyScoreErrorToastTitle', { + defaultMessage: 'An error occurred getting record with the highest anomaly score', + }) + ); + } +}; diff --git a/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseries_search_service.ts b/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseries_search_service.ts index e43ba8c87083a..0d7abdab90be0 100644 --- a/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseries_search_service.ts +++ b/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseries_search_service.ts @@ -26,7 +26,8 @@ function getMetricData( entityFields: EntityField[], earliestMs: number, latestMs: number, - intervalMs: number + intervalMs: number, + esMetricFunction?: string ): Observable { if ( isModelPlotChartableForDetector(job, detectorIndex) && @@ -88,7 +89,7 @@ function getMetricData( chartConfig.datafeedConfig.indices, entityFields, chartConfig.datafeedConfig.query, - chartConfig.metricFunction, + esMetricFunction ?? chartConfig.metricFunction, chartConfig.metricFieldName, chartConfig.timeField, earliestMs, diff --git a/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer.js b/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer.js index 720c1377d4035..e3b6e38f47bab 100644 --- a/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer.js +++ b/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer.js @@ -82,6 +82,9 @@ import { ANOMALY_DETECTION_DEFAULT_TIME_RANGE } from '../../../common/constants/ import { getControlsForDetector } from './get_controls_for_detector'; import { SeriesControls } from './components/series_controls'; import { TimeSeriesChartWithTooltips } from './components/timeseries_chart/timeseries_chart_with_tooltip'; +import { PlotByFunctionControls } from './components/plot_function_controls'; +import { aggregationTypeTransform } from '../../../common/util/anomaly_utils'; +import { getFunctionDescription } from './get_function_description'; // Used to indicate the chart is being plotted across // all partition field values, where the cardinality of the field cannot be @@ -140,6 +143,8 @@ function getTimeseriesexplorerDefaultState() { zoomTo: undefined, zoomFromFocusLoaded: undefined, zoomToFocusLoaded: undefined, + // Sets function to plot by if original function is metric + functionDescription: undefined, }; } @@ -217,6 +222,12 @@ export class TimeSeriesExplorer extends React.Component { }); }; + setFunctionDescription = (selectedFuction) => { + this.setState({ + functionDescription: selectedFuction, + }); + }; + previousChartProps = {}; previousShowAnnotations = undefined; previousShowForecast = undefined; @@ -270,7 +281,7 @@ export class TimeSeriesExplorer extends React.Component { */ getFocusData(selection) { const { selectedJobId, selectedForecastId, selectedDetectorIndex } = this.props; - const { modelPlotEnabled } = this.state; + const { modelPlotEnabled, functionDescription } = this.state; const selectedJob = mlJobService.getJob(selectedJobId); const entityControls = this.getControlsForDetector(); @@ -292,6 +303,7 @@ export class TimeSeriesExplorer extends React.Component { entityControls.filter((entity) => entity.fieldValue !== null), searchBounds, selectedJob, + functionDescription, TIME_FIELD_NAME ); } @@ -322,6 +334,7 @@ export class TimeSeriesExplorer extends React.Component { tableInterval, tableSeverity, } = this.props; + const { functionDescription } = this.state; const selectedJob = mlJobService.getJob(selectedJobId); const entityControls = this.getControlsForDetector(); @@ -335,7 +348,10 @@ export class TimeSeriesExplorer extends React.Component { earliestMs, latestMs, dateFormatTz, - ANOMALIES_TABLE_DEFAULT_QUERY_SIZE + ANOMALIES_TABLE_DEFAULT_QUERY_SIZE, + undefined, + undefined, + functionDescription ) .pipe( map((resp) => { @@ -378,6 +394,24 @@ export class TimeSeriesExplorer extends React.Component { ); }; + getFunctionDescription = async () => { + const { selectedDetectorIndex, selectedEntities, selectedJobId } = this.props; + const selectedJob = mlJobService.getJob(selectedJobId); + + const functionDescriptionToPlot = await getFunctionDescription( + { + selectedDetectorIndex, + selectedEntities, + selectedJobId, + selectedJob, + }, + this.props.toastNotificationService + ); + if (!this.unmounted) { + this.setFunctionDescription(functionDescriptionToPlot); + } + }; + setForecastId = (forecastId) => { this.props.appStateHandler(APP_STATE_ACTION.SET_FORECAST_ID, forecastId); }; @@ -392,13 +426,13 @@ export class TimeSeriesExplorer extends React.Component { zoom, } = this.props; - const { loadCounter: currentLoadCounter } = this.state; + const { loadCounter: currentLoadCounter, functionDescription } = this.state; const currentSelectedJob = mlJobService.getJob(selectedJobId); - if (currentSelectedJob === undefined) { return; } + const functionToPlotByIfMetric = aggregationTypeTransform.toES(functionDescription); this.contextChartSelectedInitCallDone = false; @@ -533,7 +567,8 @@ export class TimeSeriesExplorer extends React.Component { nonBlankEntities, searchBounds.min.valueOf(), searchBounds.max.valueOf(), - stateUpdate.contextAggregationInterval.asMilliseconds() + stateUpdate.contextAggregationInterval.asMilliseconds(), + functionToPlotByIfMetric ) .toPromise() .then((resp) => { @@ -556,7 +591,8 @@ export class TimeSeriesExplorer extends React.Component { this.getCriteriaFields(detectorIndex, entityControls), searchBounds.min.valueOf(), searchBounds.max.valueOf(), - stateUpdate.contextAggregationInterval.asMilliseconds() + stateUpdate.contextAggregationInterval.asMilliseconds(), + functionToPlotByIfMetric ) .then((resp) => { const fullRangeRecordScoreData = processRecordScoreResults(resp.results); @@ -687,7 +723,6 @@ export class TimeSeriesExplorer extends React.Component { if (detectorId !== selectedDetectorIndex) { appStateHandler(APP_STATE_ACTION.SET_DETECTOR_INDEX, detectorId); } - // Populate the map of jobs / detectors / field formatters for the selected IDs and refresh. mlFieldFormatService.populateFormats([jobId]).catch((err) => { console.log('Error populating field formats:', err); @@ -810,7 +845,7 @@ export class TimeSeriesExplorer extends React.Component { this.componentDidUpdate(); } - componentDidUpdate(previousProps) { + componentDidUpdate(previousProps, previousState) { if (previousProps === undefined || previousProps.selectedJobId !== this.props.selectedJobId) { this.contextChartSelectedInitCallDone = false; this.setState({ fullRefresh: false, loading: true }, () => { @@ -818,6 +853,15 @@ export class TimeSeriesExplorer extends React.Component { }); } + if ( + previousProps === undefined || + previousProps.selectedJobId !== this.props.selectedJobId || + previousProps.selectedDetectorIndex !== this.props.selectedDetectorIndex || + !isEqual(previousProps.selectedEntities, this.props.selectedEntities) + ) { + this.getFunctionDescription(); + } + if ( previousProps === undefined || previousProps.selectedForecastId !== this.props.selectedForecastId @@ -840,7 +884,8 @@ export class TimeSeriesExplorer extends React.Component { !isEqual(previousProps.selectedDetectorIndex, this.props.selectedDetectorIndex) || !isEqual(previousProps.selectedEntities, this.props.selectedEntities) || previousProps.selectedForecastId !== this.props.selectedForecastId || - previousProps.selectedJobId !== this.props.selectedJobId + previousProps.selectedJobId !== this.props.selectedJobId || + previousState.functionDescription !== this.state.functionDescription ) { const fullRefresh = previousProps === undefined || @@ -848,7 +893,8 @@ export class TimeSeriesExplorer extends React.Component { !isEqual(previousProps.selectedDetectorIndex, this.props.selectedDetectorIndex) || !isEqual(previousProps.selectedEntities, this.props.selectedEntities) || previousProps.selectedForecastId !== this.props.selectedForecastId || - previousProps.selectedJobId !== this.props.selectedJobId; + previousProps.selectedJobId !== this.props.selectedJobId || + previousState.functionDescription !== this.state.functionDescription; this.loadSingleMetricData(fullRefresh); } @@ -919,8 +965,8 @@ export class TimeSeriesExplorer extends React.Component { zoomTo, zoomFromFocusLoaded, zoomToFocusLoaded, + functionDescription, } = this.state; - const chartProps = { modelPlotEnabled, contextChartData, @@ -939,7 +985,6 @@ export class TimeSeriesExplorer extends React.Component { zoomToFocusLoaded, autoZoomDuration, }; - const jobs = createTimeSeriesJobData(mlJobService.jobs); if (selectedDetectorIndex === undefined || mlJobService.getJob(selectedJobId) === undefined) { @@ -992,7 +1037,6 @@ export class TimeSeriesExplorer extends React.Component { )} - + {functionDescription && ( + + )} + {arePartitioningFieldsProvided && ( @@ -1014,7 +1068,6 @@ export class TimeSeriesExplorer extends React.Component { )} - {fullRefresh && loading === true && ( diff --git a/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer_utils/get_focus_data.ts b/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer_utils/get_focus_data.ts index d1576be18d5bf..044e5dfd6fe13 100644 --- a/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer_utils/get_focus_data.ts +++ b/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer_utils/get_focus_data.ts @@ -26,6 +26,7 @@ import { mlForecastService } from '../../services/forecast_service'; import { mlFunctionToESAggregation } from '../../../../common/util/job_utils'; import { GetAnnotationsResponse } from '../../../../common/types/annotations'; import { ANNOTATION_EVENT_USER } from '../../../../common/constants/annotations'; +import { aggregationTypeTransform } from '../../../../common/util/anomaly_utils'; export interface Interval { asMilliseconds: () => number; @@ -51,8 +52,14 @@ export function getFocusData( modelPlotEnabled: boolean, nonBlankEntities: any[], searchBounds: any, - selectedJob: Job + selectedJob: Job, + functionDescription?: string | undefined ): Observable { + const esFunctionToPlotIfMetric = + functionDescription !== undefined + ? aggregationTypeTransform.toES(functionDescription) + : functionDescription; + return forkJoin([ // Query 1 - load metric data across selected time range. mlTimeSeriesSearchService.getMetricData( @@ -61,7 +68,8 @@ export function getFocusData( nonBlankEntities, searchBounds.min.valueOf(), searchBounds.max.valueOf(), - focusAggregationInterval.asMilliseconds() + focusAggregationInterval.asMilliseconds(), + esFunctionToPlotIfMetric ), // Query 2 - load all the records across selected time range for the chart anomaly markers. mlResultsService.getRecordsForCriteria( @@ -70,7 +78,8 @@ export function getFocusData( 0, searchBounds.min.valueOf(), searchBounds.max.valueOf(), - ANOMALIES_TABLE_DEFAULT_QUERY_SIZE + ANOMALIES_TABLE_DEFAULT_QUERY_SIZE, + functionDescription ), // Query 3 - load any scheduled events for the selected job. mlResultsService.getScheduledEventsByBucket( @@ -143,7 +152,8 @@ export function getFocusData( focusChartData, anomalyRecords, focusAggregationInterval, - modelPlotEnabled + modelPlotEnabled, + functionDescription ); focusChartData = processScheduledEventsForChart(focusChartData, scheduledEvents); diff --git a/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer_utils/timeseriesexplorer_utils.d.ts b/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer_utils/timeseriesexplorer_utils.d.ts index 1b7a740d90dde..4b101f888e4ea 100644 --- a/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer_utils/timeseriesexplorer_utils.d.ts +++ b/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer_utils/timeseriesexplorer_utils.d.ts @@ -16,7 +16,8 @@ export function processDataForFocusAnomalies( chartData: any, anomalyRecords: any, aggregationInterval: any, - modelPlotEnabled: any + modelPlotEnabled: any, + functionDescription: any ): any; export function processScheduledEventsForChart(chartData: any, scheduledEvents: any): any; diff --git a/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer_utils/timeseriesexplorer_utils.js b/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer_utils/timeseriesexplorer_utils.js index d24794382128d..5dc3a454e41e7 100644 --- a/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer_utils/timeseriesexplorer_utils.js +++ b/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer_utils/timeseriesexplorer_utils.js @@ -19,6 +19,7 @@ import { parseInterval } from '../../../../common/util/parse_interval'; import { getBoundsRoundedToInterval, getTimeBucketsFromCache } from '../../util/time_buckets'; import { CHARTS_POINT_TARGET, TIME_FIELD_NAME } from '../timeseriesexplorer_constants'; +import { ML_JOB_AGGREGATION } from '../../../../common/constants/aggregation_types'; // create new job objects based on standard job config objects // new job objects just contain job id, bucket span in seconds and a selected flag. @@ -100,7 +101,8 @@ export function processDataForFocusAnomalies( chartData, anomalyRecords, aggregationInterval, - modelPlotEnabled + modelPlotEnabled, + functionDescription ) { const timesToAddPointsFor = []; @@ -142,6 +144,12 @@ export function processDataForFocusAnomalies( // Look for a chart point with the same time as the record. // If none found, find closest time in chartData set. const recordTime = record[TIME_FIELD_NAME]; + if ( + record.function === ML_JOB_AGGREGATION.METRIC && + record.function_description !== functionDescription + ) + return; + const chartPoint = findChartPointForAnomalyTime(chartData, recordTime, aggregationInterval); if (chartPoint !== undefined) { // If chart aggregation interval > bucket span, there may be more than @@ -160,6 +168,10 @@ export function processDataForFocusAnomalies( chartPoint.value = record.actual; } + if (record.function === ML_JOB_AGGREGATION.METRIC) { + chartPoint.value = Array.isArray(record.actual) ? record.actual[0] : record.actual; + } + chartPoint.actual = record.actual; chartPoint.typical = record.typical; } else { diff --git a/x-pack/plugins/ml/server/models/results_service/results_service.ts b/x-pack/plugins/ml/server/models/results_service/results_service.ts index 53a35f6310978..a196f1034fdd3 100644 --- a/x-pack/plugins/ml/server/models/results_service/results_service.ts +++ b/x-pack/plugins/ml/server/models/results_service/results_service.ts @@ -54,7 +54,8 @@ export function resultsServiceProvider(mlClient: MlClient) { dateFormatTz: string, maxRecords: number = ANOMALIES_TABLE_DEFAULT_QUERY_SIZE, maxExamples: number = DEFAULT_MAX_EXAMPLES, - influencersFilterQuery: any + influencersFilterQuery?: any, + functionDescription?: string ) { // Build the query to return the matching anomaly record results. // Add criteria for the time range, record score, plus any specified job IDs. @@ -102,6 +103,13 @@ export function resultsServiceProvider(mlClient: MlClient) { }, }); }); + if (functionDescription !== undefined) { + boolCriteria.push({ + term: { + function_description: functionDescription, + }, + }); + } if (influencersFilterQuery !== undefined) { boolCriteria.push(influencersFilterQuery); diff --git a/x-pack/plugins/ml/server/routes/results_service.ts b/x-pack/plugins/ml/server/routes/results_service.ts index ce892b227c04e..e708dd71043d0 100644 --- a/x-pack/plugins/ml/server/routes/results_service.ts +++ b/x-pack/plugins/ml/server/routes/results_service.ts @@ -36,6 +36,7 @@ function getAnomaliesTableData(mlClient: MlClient, payload: any) { maxRecords, maxExamples, influencersFilterQuery, + functionDescription, } = payload; return rs.getAnomaliesTableData( jobIds, @@ -48,7 +49,8 @@ function getAnomaliesTableData(mlClient: MlClient, payload: any) { dateFormatTz, maxRecords, maxExamples, - influencersFilterQuery + influencersFilterQuery, + functionDescription ); } diff --git a/x-pack/plugins/ml/server/routes/schemas/results_service_schema.ts b/x-pack/plugins/ml/server/routes/schemas/results_service_schema.ts index 5cd0ecdfbec90..30a9054c69238 100644 --- a/x-pack/plugins/ml/server/routes/schemas/results_service_schema.ts +++ b/x-pack/plugins/ml/server/routes/schemas/results_service_schema.ts @@ -26,6 +26,7 @@ export const anomaliesTableDataSchema = schema.object({ maxRecords: schema.number(), maxExamples: schema.maybe(schema.number()), influencersFilterQuery: schema.maybe(schema.any()), + functionDescription: schema.maybe(schema.nullable(schema.string())), }); export const categoryDefinitionSchema = schema.object({ diff --git a/x-pack/plugins/rollup/public/index_pattern_creation/rollup_index_pattern_creation_config.js b/x-pack/plugins/rollup/public/index_pattern_creation/rollup_index_pattern_creation_config.js index 643cc3efb0136..e021831d2f438 100644 --- a/x-pack/plugins/rollup/public/index_pattern_creation/rollup_index_pattern_creation_config.js +++ b/x-pack/plugins/rollup/public/index_pattern_creation/rollup_index_pattern_creation_config.js @@ -161,9 +161,7 @@ export class RollupIndexPatternCreationConfig extends IndexPatternCreationConfig getFetchForWildcardOptions = () => { return { type: this.type, - params: { - rollup_index: this.rollupIndex, - }, + rollupIndex: this.rollupIndex, }; }; } diff --git a/x-pack/plugins/rollup/server/lib/map_capabilities.ts b/x-pack/plugins/rollup/server/lib/map_capabilities.ts deleted file mode 100644 index 233c6d1dd4b4b..0000000000000 --- a/x-pack/plugins/rollup/server/lib/map_capabilities.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { mergeJobConfigurations } from './jobs_compatibility'; - -export function getCapabilitiesForRollupIndices(indices: { [key: string]: any }) { - const indexNames = Object.keys(indices); - const capabilities = {} as { [key: string]: any }; - - indexNames.forEach((index) => { - try { - capabilities[index] = mergeJobConfigurations(indices[index].rollup_jobs); - } catch (e) { - capabilities[index] = { - error: e.message, - }; - } - }); - - return capabilities; -} diff --git a/x-pack/plugins/rollup/server/lib/search_strategies/rollup_search_strategy.ts b/x-pack/plugins/rollup/server/lib/search_strategies/rollup_search_strategy.ts index f439ac555aed9..dcf6629d35397 100644 --- a/x-pack/plugins/rollup/server/lib/search_strategies/rollup_search_strategy.ts +++ b/x-pack/plugins/rollup/server/lib/search_strategies/rollup_search_strategy.ts @@ -6,8 +6,11 @@ import { keyBy, isString } from 'lodash'; import { ILegacyScopedClusterClient } from 'src/core/server'; import { ReqFacade } from '../../../../../../src/plugins/vis_type_timeseries/server'; -import { mergeCapabilitiesWithFields } from '../merge_capabilities_with_fields'; -import { getCapabilitiesForRollupIndices } from '../map_capabilities'; + +import { + mergeCapabilitiesWithFields, + getCapabilitiesForRollupIndices, +} from '../../../../../../src/plugins/data/server'; const getRollupIndices = (rollupData: { [key: string]: any }) => Object.keys(rollupData); diff --git a/x-pack/plugins/rollup/server/plugin.ts b/x-pack/plugins/rollup/server/plugin.ts index fe193150fc1ca..51920af7c8cbc 100644 --- a/x-pack/plugins/rollup/server/plugin.ts +++ b/x-pack/plugins/rollup/server/plugin.ts @@ -36,8 +36,7 @@ import { registerRollupSearchStrategy } from './lib/search_strategies'; import { elasticsearchJsPlugin } from './client/elasticsearch_rollup'; import { isEsError } from './shared_imports'; import { formatEsError } from './lib/format_es_error'; -import { getCapabilitiesForRollupIndices } from './lib/map_capabilities'; -import { mergeCapabilitiesWithFields } from './lib/merge_capabilities_with_fields'; +import { getCapabilitiesForRollupIndices } from '../../../../src/plugins/data/server'; interface RollupContext { client: ILegacyScopedClusterClient; @@ -107,7 +106,6 @@ export class RollupPlugin implements Plugin { isEsError, formatEsError, getCapabilitiesForRollupIndices, - mergeCapabilitiesWithFields, }, sharedImports: { IndexPatternsFetcher, diff --git a/x-pack/plugins/rollup/server/routes/api/index_patterns/index.ts b/x-pack/plugins/rollup/server/routes/api/index_patterns/index.ts deleted file mode 100644 index 7bf525ca4aa98..0000000000000 --- a/x-pack/plugins/rollup/server/routes/api/index_patterns/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { RouteDependencies } from '../../../types'; -import { registerFieldsForWildcardRoute } from './register_fields_for_wildcard_route'; - -export function registerIndexPatternsRoutes(dependencies: RouteDependencies) { - registerFieldsForWildcardRoute(dependencies); -} diff --git a/x-pack/plugins/rollup/server/routes/api/index_patterns/register_fields_for_wildcard_route.ts b/x-pack/plugins/rollup/server/routes/api/index_patterns/register_fields_for_wildcard_route.ts deleted file mode 100644 index df9907fbf731a..0000000000000 --- a/x-pack/plugins/rollup/server/routes/api/index_patterns/register_fields_for_wildcard_route.ts +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { keyBy } from 'lodash'; -import { schema } from '@kbn/config-schema'; -import { Field } from '../../../lib/merge_capabilities_with_fields'; -import { RouteDependencies } from '../../../types'; -import type { IndexPatternsFetcher as IndexPatternsFetcherType } from '../../../../../../../src/plugins/data/server'; - -const parseMetaFields = (metaFields: string | string[]) => { - let parsedFields: string[] = []; - if (typeof metaFields === 'string') { - parsedFields = JSON.parse(metaFields); - } else { - parsedFields = metaFields; - } - return parsedFields; -}; - -const getFieldsForWildcardRequest = async ( - context: any, - request: any, - response: any, - IndexPatternsFetcher: typeof IndexPatternsFetcherType -) => { - const { asCurrentUser } = context.core.elasticsearch.client; - const indexPatterns = new IndexPatternsFetcher(asCurrentUser); - const { pattern, meta_fields: metaFields } = request.query; - - let parsedFields: string[] = []; - try { - parsedFields = parseMetaFields(metaFields); - } catch (error) { - return response.badRequest({ - body: error, - }); - } - - try { - const fields = await indexPatterns.getFieldsForWildcard({ - pattern, - metaFields: parsedFields, - }); - - return response.ok({ - body: { fields }, - headers: { - 'content-type': 'application/json', - }, - }); - } catch (error) { - return response.notFound(); - } -}; - -/** - * Get list of fields for rollup index pattern, in the format of regular index pattern fields - */ -export const registerFieldsForWildcardRoute = ({ - router, - license, - lib: { isEsError, formatEsError, getCapabilitiesForRollupIndices, mergeCapabilitiesWithFields }, - sharedImports: { IndexPatternsFetcher }, -}: RouteDependencies) => { - const querySchema = schema.object({ - pattern: schema.string(), - meta_fields: schema.arrayOf(schema.string(), { - defaultValue: [], - }), - params: schema.string({ - validate(value) { - try { - const params = JSON.parse(value); - const keys = Object.keys(params); - const { rollup_index: rollupIndex } = params; - - if (!rollupIndex) { - return '[request query.params]: "rollup_index" is required'; - } else if (keys.length > 1) { - const invalidParams = keys.filter((key) => key !== 'rollup_index'); - return `[request query.params]: ${invalidParams.join(', ')} is not allowed`; - } - } catch (err) { - return '[request query.params]: expected JSON string'; - } - }, - }), - }); - - router.get( - { - path: '/api/index_patterns/rollup/_fields_for_wildcard', - validate: { - query: querySchema, - }, - }, - license.guardApiRoute(async (context, request, response) => { - const { params, meta_fields: metaFields } = request.query; - - try { - // Make call and use field information from response - const { payload } = await getFieldsForWildcardRequest( - context, - request, - response, - IndexPatternsFetcher - ); - const fields = payload.fields; - const parsedParams = JSON.parse(params); - const rollupIndex = parsedParams.rollup_index; - const rollupFields: Field[] = []; - const fieldsFromFieldCapsApi: { [key: string]: any } = keyBy(fields, 'name'); - const rollupIndexCapabilities = getCapabilitiesForRollupIndices( - await context.rollup!.client.callAsCurrentUser('rollup.rollupIndexCapabilities', { - indexPattern: rollupIndex, - }) - )[rollupIndex].aggs; - - // Keep meta fields - metaFields.forEach( - (field: string) => - fieldsFromFieldCapsApi[field] && rollupFields.push(fieldsFromFieldCapsApi[field]) - ); - - const mergedRollupFields = mergeCapabilitiesWithFields( - rollupIndexCapabilities, - fieldsFromFieldCapsApi, - rollupFields - ); - return response.ok({ body: { fields: mergedRollupFields } }); - } catch (err) { - if (isEsError(err)) { - return response.customError({ statusCode: err.statusCode, body: err }); - } - return response.internalError({ body: err }); - } - }) - ); -}; diff --git a/x-pack/plugins/rollup/server/routes/index.ts b/x-pack/plugins/rollup/server/routes/index.ts index b25480855b4a2..322003c0ee325 100644 --- a/x-pack/plugins/rollup/server/routes/index.ts +++ b/x-pack/plugins/rollup/server/routes/index.ts @@ -6,13 +6,11 @@ import { RouteDependencies } from '../types'; -import { registerIndexPatternsRoutes } from './api/index_patterns'; import { registerIndicesRoutes } from './api/indices'; import { registerJobsRoutes } from './api/jobs'; import { registerSearchRoutes } from './api/search'; export function registerApiRoutes(dependencies: RouteDependencies) { - registerIndexPatternsRoutes(dependencies); registerIndicesRoutes(dependencies); registerJobsRoutes(dependencies); registerSearchRoutes(dependencies); diff --git a/x-pack/plugins/rollup/server/types.ts b/x-pack/plugins/rollup/server/types.ts index b167806cf8d5d..89e13e69c4da2 100644 --- a/x-pack/plugins/rollup/server/types.ts +++ b/x-pack/plugins/rollup/server/types.ts @@ -8,6 +8,7 @@ import { IRouter } from 'src/core/server'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; import { VisTypeTimeseriesSetup } from 'src/plugins/vis_type_timeseries/server'; +import { getCapabilitiesForRollupIndices } from 'src/plugins/data/server'; import { IndexManagementPluginSetup } from '../../index_management/server'; import { PluginSetupContract as FeaturesPluginSetup } from '../../features/server'; import { LicensingPluginSetup } from '../../licensing/server'; @@ -15,8 +16,6 @@ import { License } from './services'; import { IndexPatternsFetcher } from './shared_imports'; import { isEsError } from './shared_imports'; import { formatEsError } from './lib/format_es_error'; -import { getCapabilitiesForRollupIndices } from './lib/map_capabilities'; -import { mergeCapabilitiesWithFields } from './lib/merge_capabilities_with_fields'; export interface Dependencies { indexManagement?: IndexManagementPluginSetup; @@ -33,7 +32,6 @@ export interface RouteDependencies { isEsError: typeof isEsError; formatEsError: typeof formatEsError; getCapabilitiesForRollupIndices: typeof getCapabilitiesForRollupIndices; - mergeCapabilitiesWithFields: typeof mergeCapabilitiesWithFields; }; sharedImports: { IndexPatternsFetcher: typeof IndexPatternsFetcher; diff --git a/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.tsx b/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.tsx index 2b7ed0079f291..37747f9a1ccfa 100644 --- a/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.tsx +++ b/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.tsx @@ -260,6 +260,10 @@ export class UsersGridPage extends Component { { { expect(mockOptions.client.callAsInternalUser).not.toHaveBeenCalled(); }); + it('does not start SPNEGO for Ajax requests.', async () => { + const request = httpServerMock.createKibanaRequest({ headers: { 'kbn-xsrf': 'xsrf' } }); + await expect(provider.authenticate(request)).resolves.toEqual( + AuthenticationResult.notHandled() + ); + + expect(mockOptions.client.asScoped).not.toHaveBeenCalled(); + expect(mockOptions.client.callAsInternalUser).not.toHaveBeenCalled(); + }); + it('succeeds if state contains a valid token.', async () => { const user = mockAuthenticatedUser(); const request = httpServerMock.createKibanaRequest({ headers: {} }); @@ -442,9 +452,6 @@ describe('KerberosAuthenticationProvider', () => { }); it('fails with `Negotiate` challenge if both access and refresh tokens from the state are expired and backend supports Kerberos.', async () => { - const request = httpServerMock.createKibanaRequest(); - const tokenPair = { accessToken: 'expired-token', refreshToken: 'some-valid-refresh-token' }; - const failureReason = LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError( new (errors.AuthenticationException as any)('Unauthorized', { body: { error: { header: { 'WWW-Authenticate': 'Negotiate' } } }, @@ -456,37 +463,45 @@ describe('KerberosAuthenticationProvider', () => { mockOptions.tokens.refresh.mockResolvedValue(null); - await expect(provider.authenticate(request, tokenPair)).resolves.toEqual( + const nonAjaxRequest = httpServerMock.createKibanaRequest(); + const nonAjaxTokenPair = { + accessToken: 'expired-token', + refreshToken: 'some-valid-refresh-token', + }; + await expect(provider.authenticate(nonAjaxRequest, nonAjaxTokenPair)).resolves.toEqual( AuthenticationResult.failed(failureReason, { authResponseHeaders: { 'WWW-Authenticate': 'Negotiate' }, }) ); - expect(mockOptions.tokens.refresh).toHaveBeenCalledTimes(1); - expect(mockOptions.tokens.refresh).toHaveBeenCalledWith(tokenPair.refreshToken); - }); - - it('does not re-start SPNEGO if both access and refresh tokens from the state are expired.', async () => { - const request = httpServerMock.createKibanaRequest({ routeAuthRequired: false }); - const tokenPair = { accessToken: 'expired-token', refreshToken: 'some-valid-refresh-token' }; - - const failureReason = LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError( - new (errors.AuthenticationException as any)('Unauthorized', { - body: { error: { header: { 'WWW-Authenticate': 'Negotiate' } } }, + const ajaxRequest = httpServerMock.createKibanaRequest({ headers: { 'kbn-xsrf': 'xsrf' } }); + const ajaxTokenPair = { + accessToken: 'expired-token', + refreshToken: 'ajax-some-valid-refresh-token', + }; + await expect(provider.authenticate(ajaxRequest, ajaxTokenPair)).resolves.toEqual( + AuthenticationResult.failed(failureReason, { + authResponseHeaders: { 'WWW-Authenticate': 'Negotiate' }, }) ); - const mockScopedClusterClient = elasticsearchServiceMock.createLegacyScopedClusterClient(); - mockScopedClusterClient.callAsCurrentUser.mockRejectedValue(failureReason); - mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); - mockOptions.tokens.refresh.mockResolvedValue(null); - - await expect(provider.authenticate(request, tokenPair)).resolves.toEqual( - AuthenticationResult.notHandled() + const optionalAuthRequest = httpServerMock.createKibanaRequest({ routeAuthRequired: false }); + const optionalAuthTokenPair = { + accessToken: 'expired-token', + refreshToken: 'optional-some-valid-refresh-token', + }; + await expect( + provider.authenticate(optionalAuthRequest, optionalAuthTokenPair) + ).resolves.toEqual( + AuthenticationResult.failed(failureReason, { + authResponseHeaders: { 'WWW-Authenticate': 'Negotiate' }, + }) ); - expect(mockOptions.tokens.refresh).toHaveBeenCalledTimes(1); - expect(mockOptions.tokens.refresh).toHaveBeenCalledWith(tokenPair.refreshToken); + expect(mockOptions.tokens.refresh).toHaveBeenCalledTimes(3); + expect(mockOptions.tokens.refresh).toHaveBeenCalledWith(nonAjaxTokenPair.refreshToken); + expect(mockOptions.tokens.refresh).toHaveBeenCalledWith(ajaxTokenPair.refreshToken); + expect(mockOptions.tokens.refresh).toHaveBeenCalledWith(optionalAuthTokenPair.refreshToken); }); }); diff --git a/x-pack/plugins/security/server/authentication/providers/kerberos.ts b/x-pack/plugins/security/server/authentication/providers/kerberos.ts index 34ed9ac920e93..fa578b9dca45f 100644 --- a/x-pack/plugins/security/server/authentication/providers/kerberos.ts +++ b/x-pack/plugins/security/server/authentication/providers/kerberos.ts @@ -13,6 +13,7 @@ import { import { AuthenticationResult } from '../authentication_result'; import { DeauthenticationResult } from '../deauthentication_result'; import { HTTPAuthorizationHeader } from '../http_authentication'; +import { canRedirectRequest } from '../can_redirect_request'; import { Tokens, TokenPair } from '../tokens'; import { BaseAuthenticationProvider } from './base'; @@ -32,8 +33,9 @@ const WWWAuthenticateHeaderName = 'WWW-Authenticate'; * @param request Request instance. */ function canStartNewSession(request: KibanaRequest) { - // We should try to establish new session only if request requires authentication. - return request.route.options.authRequired === true; + // We should try to establish new session only if request requires authentication and it's not an XHR request. + // Technically we can authenticate XHR requests too, but we don't want these to create a new session unintentionally. + return canRedirectRequest(request) && request.route.options.authRequired === true; } /** @@ -75,11 +77,8 @@ export class KerberosAuthenticationProvider extends BaseAuthenticationProvider { return AuthenticationResult.notHandled(); } - let authenticationResult = authorizationHeader - ? await this.authenticateWithNegotiateScheme(request) - : AuthenticationResult.notHandled(); - - if (state && authenticationResult.notHandled()) { + let authenticationResult = AuthenticationResult.notHandled(); + if (state) { authenticationResult = await this.authenticateViaState(request, state); if ( authenticationResult.failed() && @@ -89,11 +88,15 @@ export class KerberosAuthenticationProvider extends BaseAuthenticationProvider { } } - // If we couldn't authenticate by means of all methods above, let's try to check if Elasticsearch can - // start authentication mechanism negotiation, otherwise just return authentication result we have. - return authenticationResult.notHandled() && canStartNewSession(request) - ? await this.authenticateViaSPNEGO(request, state) - : authenticationResult; + if (!authenticationResult.notHandled() || !canStartNewSession(request)) { + return authenticationResult; + } + + // If we couldn't authenticate by means of all methods above, let's check if we're already at the authentication + // mechanism negotiation stage, otherwise check with Elasticsearch if we can start it. + return authorizationHeader + ? await this.authenticateWithNegotiateScheme(request) + : await this.authenticateViaSPNEGO(request, state); } /** @@ -264,12 +267,12 @@ export class KerberosAuthenticationProvider extends BaseAuthenticationProvider { return AuthenticationResult.failed(err); } - // If refresh token is no longer valid, then we should clear session and renegotiate using SPNEGO. + // If refresh token is no longer valid, let's try to renegotiate new tokens using SPNEGO. We + // allow this because expired underlying token is an implementation detail and Kibana user + // facing session is still valid. if (refreshedTokenPair === null) { - this.logger.debug('Both access and refresh tokens are expired.'); - return canStartNewSession(request) - ? this.authenticateViaSPNEGO(request, state) - : AuthenticationResult.notHandled(); + this.logger.debug('Both access and refresh tokens are expired. Re-authenticating...'); + return this.authenticateViaSPNEGO(request, state); } try { diff --git a/x-pack/plugins/security/server/authentication/providers/pki.test.ts b/x-pack/plugins/security/server/authentication/providers/pki.test.ts index 969682b225ceb..94308ab5f2403 100644 --- a/x-pack/plugins/security/server/authentication/providers/pki.test.ts +++ b/x-pack/plugins/security/server/authentication/providers/pki.test.ts @@ -295,6 +295,22 @@ describe('PKIAuthenticationProvider', () => { expect(mockOptions.client.callAsInternalUser).not.toHaveBeenCalled(); }); + it('does not exchange peer certificate to access token for Ajax requests.', async () => { + const request = httpServerMock.createKibanaRequest({ + headers: { 'kbn-xsrf': 'xsrf' }, + socket: getMockSocket({ + authorized: true, + peerCertificate: getMockPeerCertificate(['2A:7A:C2:DD', '3B:8B:D3:EE']), + }), + }); + await expect(provider.authenticate(request)).resolves.toEqual( + AuthenticationResult.notHandled() + ); + + expect(mockOptions.client.asScoped).not.toHaveBeenCalled(); + expect(mockOptions.client.callAsInternalUser).not.toHaveBeenCalled(); + }); + it('fails with non-401 error if state is available, peer is authorized, but certificate is not available.', async () => { const request = httpServerMock.createKibanaRequest({ socket: getMockSocket({ authorized: true }), @@ -383,14 +399,7 @@ describe('PKIAuthenticationProvider', () => { }); it('gets a new access token even if existing token is expired.', async () => { - const user = mockAuthenticatedUser(); - const request = httpServerMock.createKibanaRequest({ - socket: getMockSocket({ - authorized: true, - peerCertificate: getMockPeerCertificate(['2A:7A:C2:DD', '3B:8B:D3:EE']), - }), - }); - const state = { accessToken: 'existing-token', peerCertificateFingerprint256: '2A:7A:C2:DD' }; + const user = mockAuthenticatedUser({ authentication_provider: { type: 'pki', name: 'pki' } }); const mockScopedClusterClient = elasticsearchServiceMock.createLegacyScopedClusterClient(); mockScopedClusterClient.callAsCurrentUser @@ -399,55 +408,102 @@ describe('PKIAuthenticationProvider', () => { LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) ) // In response to a call with a new token. + .mockResolvedValueOnce(user) // In response to call with an expired token. + .mockRejectedValueOnce( + LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) + ) + // In response to a call with a new token. + .mockResolvedValueOnce(user) // In response to call with an expired token. + .mockRejectedValueOnce( + LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) + ) + // In response to a call with a new token. .mockResolvedValueOnce(user); mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); mockOptions.client.callAsInternalUser.mockResolvedValue({ access_token: 'access-token' }); - await expect(provider.authenticate(request, state)).resolves.toEqual( - AuthenticationResult.succeeded( - { ...user, authentication_provider: { type: 'pki', name: 'pki' } }, - { - authHeaders: { authorization: 'Bearer access-token' }, - state: { accessToken: 'access-token', peerCertificateFingerprint256: '2A:7A:C2:DD' }, - } - ) + const nonAjaxRequest = httpServerMock.createKibanaRequest({ + socket: getMockSocket({ + authorized: true, + peerCertificate: getMockPeerCertificate(['2A:7A:C2:DD', '3B:8B:D3:EE']), + }), + }); + const nonAjaxState = { + accessToken: 'existing-token', + peerCertificateFingerprint256: '2A:7A:C2:DD', + }; + await expect(provider.authenticate(nonAjaxRequest, nonAjaxState)).resolves.toEqual( + AuthenticationResult.succeeded(user, { + authHeaders: { authorization: 'Bearer access-token' }, + state: { accessToken: 'access-token', peerCertificateFingerprint256: '2A:7A:C2:DD' }, + }) ); - expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledTimes(1); - expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith('shield.delegatePKI', { - body: { - x509_certificate_chain: [ - 'fingerprint:2A:7A:C2:DD:base64', - 'fingerprint:3B:8B:D3:EE:base64', - ], - }, + const ajaxRequest = httpServerMock.createKibanaRequest({ + headers: { 'kbn-xsrf': 'xsrf' }, + socket: getMockSocket({ + authorized: true, + peerCertificate: getMockPeerCertificate(['3A:7A:C2:DD', '3B:8B:D3:EE']), + }), }); + const ajaxState = { + accessToken: 'existing-token', + peerCertificateFingerprint256: '3A:7A:C2:DD', + }; + await expect(provider.authenticate(ajaxRequest, ajaxState)).resolves.toEqual( + AuthenticationResult.succeeded(user, { + authHeaders: { authorization: 'Bearer access-token' }, + state: { accessToken: 'access-token', peerCertificateFingerprint256: '3A:7A:C2:DD' }, + }) + ); - expect(request.headers).not.toHaveProperty('authorization'); - }); - - it('does not exchange peer certificate to a new access token even if existing token is expired and request does not require authentication.', async () => { - const request = httpServerMock.createKibanaRequest({ + const optionalAuthRequest = httpServerMock.createKibanaRequest({ routeAuthRequired: false, socket: getMockSocket({ authorized: true, - peerCertificate: getMockPeerCertificate(['2A:7A:C2:DD', '3B:8B:D3:EE']), + peerCertificate: getMockPeerCertificate(['4A:7A:C2:DD', '3B:8B:D3:EE']), }), }); - const state = { accessToken: 'existing-token', peerCertificateFingerprint256: '2A:7A:C2:DD' }; - - const mockScopedClusterClient = elasticsearchServiceMock.createLegacyScopedClusterClient(); - mockScopedClusterClient.callAsCurrentUser.mockRejectedValueOnce( - LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) + const optionalAuthState = { + accessToken: 'existing-token', + peerCertificateFingerprint256: '4A:7A:C2:DD', + }; + await expect(provider.authenticate(optionalAuthRequest, optionalAuthState)).resolves.toEqual( + AuthenticationResult.succeeded(user, { + authHeaders: { authorization: 'Bearer access-token' }, + state: { accessToken: 'access-token', peerCertificateFingerprint256: '4A:7A:C2:DD' }, + }) ); - mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); - await expect(provider.authenticate(request, state)).resolves.toEqual( - AuthenticationResult.notHandled() - ); + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledTimes(3); + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith('shield.delegatePKI', { + body: { + x509_certificate_chain: [ + 'fingerprint:2A:7A:C2:DD:base64', + 'fingerprint:3B:8B:D3:EE:base64', + ], + }, + }); + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith('shield.delegatePKI', { + body: { + x509_certificate_chain: [ + 'fingerprint:3A:7A:C2:DD:base64', + 'fingerprint:3B:8B:D3:EE:base64', + ], + }, + }); + expect(mockOptions.client.callAsInternalUser).toHaveBeenCalledWith('shield.delegatePKI', { + body: { + x509_certificate_chain: [ + 'fingerprint:4A:7A:C2:DD:base64', + 'fingerprint:3B:8B:D3:EE:base64', + ], + }, + }); - expect(mockOptions.client.callAsInternalUser).not.toHaveBeenCalled(); - expect(request.headers).not.toHaveProperty('authorization'); + expect(nonAjaxRequest.headers).not.toHaveProperty('authorization'); + expect(ajaxRequest.headers).not.toHaveProperty('authorization'); + expect(optionalAuthRequest.headers).not.toHaveProperty('authorization'); }); it('fails with 401 if existing token is expired, but certificate is not present.', async () => { diff --git a/x-pack/plugins/security/server/authentication/providers/pki.ts b/x-pack/plugins/security/server/authentication/providers/pki.ts index 9214a025484fe..3629a0ac34f02 100644 --- a/x-pack/plugins/security/server/authentication/providers/pki.ts +++ b/x-pack/plugins/security/server/authentication/providers/pki.ts @@ -10,6 +10,7 @@ import { KibanaRequest } from '../../../../../../src/core/server'; import { AuthenticationResult } from '../authentication_result'; import { DeauthenticationResult } from '../deauthentication_result'; import { HTTPAuthorizationHeader } from '../http_authentication'; +import { canRedirectRequest } from '../can_redirect_request'; import { Tokens } from '../tokens'; import { BaseAuthenticationProvider } from './base'; @@ -33,8 +34,9 @@ interface ProviderState { * @param request Request instance. */ function canStartNewSession(request: KibanaRequest) { - // We should try to establish new session only if request requires authentication. - return request.route.options.authRequired === true; + // We should try to establish new session only if request requires authentication and it's not an XHR request. + // Technically we can authenticate XHR requests too, but we don't want these to create a new session unintentionally. + return canRedirectRequest(request) && request.route.options.authRequired === true; } /** @@ -75,12 +77,14 @@ export class PKIAuthenticationProvider extends BaseAuthenticationProvider { authenticationResult = await this.authenticateViaState(request, state); // If access token expired or doesn't match to the certificate fingerprint we should try to get - // a new one in exchange to peer certificate chain assuming request can initiate new session. + // a new one in exchange to peer certificate chain. Since we know that we had a valid session + // before we can safely assume that it's desired to automatically re-create session even for XHR + // requests. const invalidAccessToken = authenticationResult.notHandled() || (authenticationResult.failed() && Tokens.isAccessTokenExpiredError(authenticationResult.error)); - if (invalidAccessToken && canStartNewSession(request)) { + if (invalidAccessToken) { authenticationResult = await this.authenticateViaPeerCertificate(request); // If we have an active session that we couldn't use to authenticate user and at the same time // we couldn't use peer's certificate to establish a new one, then we should respond with 401 @@ -88,14 +92,12 @@ export class PKIAuthenticationProvider extends BaseAuthenticationProvider { if (authenticationResult.notHandled()) { return AuthenticationResult.failed(Boom.unauthorized()); } - } else if (invalidAccessToken) { - return AuthenticationResult.notHandled(); } } - // If we couldn't authenticate by means of all methods above, let's try to check if we can authenticate - // request using its peer certificate chain, otherwise just return authentication result we have. - // We shouldn't establish new session if authentication isn't required for this particular request. + // If we couldn't authenticate by means of all methods above, let's check if the request is allowed + // to start a new session, and if so try to authenticate request using its peer certificate chain, + // otherwise just return authentication result we have. return authenticationResult.notHandled() && canStartNewSession(request) ? await this.authenticateViaPeerCertificate(request) : authenticationResult; diff --git a/x-pack/plugins/security_solution/README.md b/x-pack/plugins/security_solution/README.md index 6680dbf1a149b..d9aa4a6cfebbe 100644 --- a/x-pack/plugins/security_solution/README.md +++ b/x-pack/plugins/security_solution/README.md @@ -97,7 +97,7 @@ PACKAGE_REGISTRY_URL_OVERRIDE= { diff --git a/x-pack/plugins/security_solution/common/endpoint/policy/migrations/to_v7_11.0.ts b/x-pack/plugins/security_solution/common/endpoint/policy/migrations/to_v7_11.0.ts index 8c2dabae21bbd..551e0ecfdcb4f 100644 --- a/x-pack/plugins/security_solution/common/endpoint/policy/migrations/to_v7_11.0.ts +++ b/x-pack/plugins/security_solution/common/endpoint/policy/migrations/to_v7_11.0.ts @@ -6,7 +6,7 @@ import { SavedObjectMigrationFn, SavedObjectUnsanitizedDoc } from 'kibana/server'; import { cloneDeep } from 'lodash'; -import { PackagePolicy } from '../../../../../ingest_manager/common'; +import { PackagePolicy } from '../../../../../fleet/common'; export const migratePackagePolicyToV7110: SavedObjectMigrationFn = ( packagePolicyDoc diff --git a/x-pack/plugins/security_solution/common/endpoint/types/index.ts b/x-pack/plugins/security_solution/common/endpoint/types/index.ts index 79157018c315a..1d64578a6a7f1 100644 --- a/x-pack/plugins/security_solution/common/endpoint/types/index.ts +++ b/x-pack/plugins/security_solution/common/endpoint/types/index.ts @@ -5,7 +5,7 @@ */ import { ApplicationStart } from 'kibana/public'; -import { NewPackagePolicy, PackagePolicy } from '../../../../ingest_manager/common'; +import { NewPackagePolicy, PackagePolicy } from '../../../../fleet/common'; import { ManifestSchema } from '../schema/manifest'; export * from './trusted_apps'; diff --git a/x-pack/plugins/security_solution/public/app/home/setup.tsx b/x-pack/plugins/security_solution/public/app/home/setup.tsx index 3f4b0c19e7035..c3567e34a0411 100644 --- a/x-pack/plugins/security_solution/public/app/home/setup.tsx +++ b/x-pack/plugins/security_solution/public/app/home/setup.tsx @@ -6,7 +6,7 @@ import * as React from 'react'; import { i18n } from '@kbn/i18n'; import { NotificationsStart } from 'kibana/public'; -import { IngestManagerStart } from '../../../../ingest_manager/public'; +import { IngestManagerStart } from '../../../../fleet/public'; export const Setup: React.FunctionComponent<{ ingestManager: IngestManagerStart; diff --git a/x-pack/plugins/security_solution/public/common/containers/events/last_event_time/index.ts b/x-pack/plugins/security_solution/public/common/containers/events/last_event_time/index.ts index 2d85c1d60a7b0..b6938bc18a88d 100644 --- a/x-pack/plugins/security_solution/public/common/containers/events/last_event_time/index.ts +++ b/x-pack/plugins/security_solution/public/common/containers/events/last_event_time/index.ts @@ -18,10 +18,10 @@ import { LastEventIndexKey, } from '../../../../../common/search_strategy/timeline'; import { - AbortError, isCompleteResponse, isErrorResponse, } from '../../../../../../../../src/plugins/data/common'; +import { AbortError } from '../../../../../../../../src/plugins/kibana_utils/common'; import * as i18n from './translations'; import { DocValueFields } from '../../../../../common/search_strategy'; diff --git a/x-pack/plugins/security_solution/public/common/containers/matrix_histogram/index.ts b/x-pack/plugins/security_solution/public/common/containers/matrix_histogram/index.ts index 8db513da1f3a1..a2cf59314d149 100644 --- a/x-pack/plugins/security_solution/public/common/containers/matrix_histogram/index.ts +++ b/x-pack/plugins/security_solution/public/common/containers/matrix_histogram/index.ts @@ -18,11 +18,8 @@ import { MatrixHistogramStrategyResponse, MatrixHistogramData, } from '../../../../common/search_strategy/security_solution'; -import { - AbortError, - isErrorResponse, - isCompleteResponse, -} from '../../../../../../../src/plugins/data/common'; +import { isErrorResponse, isCompleteResponse } from '../../../../../../../src/plugins/data/common'; +import { AbortError } from '../../../../../../../src/plugins/kibana_utils/common'; import { getInspectResponse } from '../../../helpers'; import { InspectResponse } from '../../../types'; import * as i18n from './translations'; diff --git a/x-pack/plugins/security_solution/public/common/containers/source/index.tsx b/x-pack/plugins/security_solution/public/common/containers/source/index.tsx index 47e550b2ced0f..7e73a40f2f748 100644 --- a/x-pack/plugins/security_solution/public/common/containers/source/index.tsx +++ b/x-pack/plugins/security_solution/public/common/containers/source/index.tsx @@ -18,7 +18,7 @@ import { BrowserField, BrowserFields, } from '../../../../common/search_strategy/index_fields'; -import { AbortError } from '../../../../../../../src/plugins/data/common'; +import { AbortError } from '../../../../../../../src/plugins/kibana_utils/common'; import { useShallowEqualSelector } from '../../../common/hooks/use_selector'; import * as i18n from './translations'; import { SourcererScopeName } from '../../store/sourcerer/model'; diff --git a/x-pack/plugins/security_solution/public/common/hooks/endpoint/upgrade.ts b/x-pack/plugins/security_solution/public/common/hooks/endpoint/upgrade.ts index 48f826d1c3a91..01b14bd411282 100644 --- a/x-pack/plugins/security_solution/public/common/hooks/endpoint/upgrade.ts +++ b/x-pack/plugins/security_solution/public/common/hooks/endpoint/upgrade.ts @@ -11,7 +11,7 @@ import { appRoutesService, CheckPermissionsResponse, BulkInstallPackagesResponse, -} from '../../../../../ingest_manager/common'; +} from '../../../../../fleet/common'; import { StartServices } from '../../../types'; import { useIngestEnabledCheck } from './ingest_enabled'; diff --git a/x-pack/plugins/security_solution/public/common/hooks/eql/use_eql_preview.ts b/x-pack/plugins/security_solution/public/common/hooks/eql/use_eql_preview.ts index 93236381753bf..1f4424a4f28b8 100644 --- a/x-pack/plugins/security_solution/public/common/hooks/eql/use_eql_preview.ts +++ b/x-pack/plugins/security_solution/public/common/hooks/eql/use_eql_preview.ts @@ -11,11 +11,11 @@ import { takeUntil } from 'rxjs/operators'; import * as i18n from '../translations'; import { useKibana } from '../../../common/lib/kibana'; import { - AbortError, isCompleteResponse, isErrorResponse, isPartialResponse, } from '../../../../../../../src/plugins/data/common'; +import { AbortError } from '../../../../../../../src/plugins/kibana_utils/common'; import { EqlSearchStrategyRequest, EqlSearchStrategyResponse, diff --git a/x-pack/plugins/security_solution/public/common/mock/endpoint/dependencies_start_mock.ts b/x-pack/plugins/security_solution/public/common/mock/endpoint/dependencies_start_mock.ts index 5f8ab723df107..ff3fe7517e64a 100644 --- a/x-pack/plugins/security_solution/public/common/mock/endpoint/dependencies_start_mock.ts +++ b/x-pack/plugins/security_solution/public/common/mock/endpoint/dependencies_start_mock.ts @@ -4,10 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - IngestManagerStart, - registerPackagePolicyComponent, -} from '../../../../../ingest_manager/public'; +import { IngestManagerStart, registerPackagePolicyComponent } from '../../../../../fleet/public'; import { dataPluginMock, Start as DataPublicStartMock, diff --git a/x-pack/plugins/security_solution/public/hosts/containers/authentications/index.tsx b/x-pack/plugins/security_solution/public/hosts/containers/authentications/index.tsx index 3cc87bdd275df..d964366dc5f3d 100644 --- a/x-pack/plugins/security_solution/public/hosts/containers/authentications/index.tsx +++ b/x-pack/plugins/security_solution/public/hosts/containers/authentications/index.tsx @@ -8,11 +8,8 @@ import { noop } from 'lodash/fp'; import { useCallback, useEffect, useRef, useState } from 'react'; import deepEqual from 'fast-deep-equal'; -import { - AbortError, - isCompleteResponse, - isErrorResponse, -} from '../../../../../../../src/plugins/data/common'; +import { isCompleteResponse, isErrorResponse } from '../../../../../../../src/plugins/data/common'; +import { AbortError } from '../../../../../../../src/plugins/kibana_utils/common'; import { HostsQueries } from '../../../../common/search_strategy/security_solution'; import { diff --git a/x-pack/plugins/security_solution/public/hosts/containers/hosts/details/_index.tsx b/x-pack/plugins/security_solution/public/hosts/containers/hosts/details/_index.tsx index 61c3f63bdb4aa..54381d1ffd836 100644 --- a/x-pack/plugins/security_solution/public/hosts/containers/hosts/details/_index.tsx +++ b/x-pack/plugins/security_solution/public/hosts/containers/hosts/details/_index.tsx @@ -21,10 +21,10 @@ import { import * as i18n from './translations'; import { - AbortError, isCompleteResponse, isErrorResponse, } from '../../../../../../../../src/plugins/data/common'; +import { AbortError } from '../../../../../../../../src/plugins/kibana_utils/common'; import { getInspectResponse } from '../../../../helpers'; import { InspectResponse } from '../../../../types'; diff --git a/x-pack/plugins/security_solution/public/hosts/containers/hosts/first_last_seen/index.tsx b/x-pack/plugins/security_solution/public/hosts/containers/hosts/first_last_seen/index.tsx index cc944a59571f1..1cb13da2048ad 100644 --- a/x-pack/plugins/security_solution/public/hosts/containers/hosts/first_last_seen/index.tsx +++ b/x-pack/plugins/security_solution/public/hosts/containers/hosts/first_last_seen/index.tsx @@ -17,10 +17,10 @@ import { import * as i18n from './translations'; import { DocValueFields } from '../../../../../common/search_strategy'; import { - AbortError, isCompleteResponse, isErrorResponse, } from '../../../../../../../../src/plugins/data/common'; +import { AbortError } from '../../../../../../../../src/plugins/kibana_utils/common'; const ID = 'firstLastSeenHostQuery'; diff --git a/x-pack/plugins/security_solution/public/hosts/containers/hosts/index.tsx b/x-pack/plugins/security_solution/public/hosts/containers/hosts/index.tsx index 1228f94c7a39a..c1081d22e12a4 100644 --- a/x-pack/plugins/security_solution/public/hosts/containers/hosts/index.tsx +++ b/x-pack/plugins/security_solution/public/hosts/containers/hosts/index.tsx @@ -25,11 +25,8 @@ import { import { ESTermQuery } from '../../../../common/typed_json'; import * as i18n from './translations'; -import { - AbortError, - isCompleteResponse, - isErrorResponse, -} from '../../../../../../../src/plugins/data/common'; +import { isCompleteResponse, isErrorResponse } from '../../../../../../../src/plugins/data/common'; +import { AbortError } from '../../../../../../../src/plugins/kibana_utils/common'; import { getInspectResponse } from '../../../helpers'; import { InspectResponse } from '../../../types'; diff --git a/x-pack/plugins/security_solution/public/hosts/containers/kpi_hosts/authentications/index.tsx b/x-pack/plugins/security_solution/public/hosts/containers/kpi_hosts/authentications/index.tsx index d433fef98bece..281f8489fce0f 100644 --- a/x-pack/plugins/security_solution/public/hosts/containers/kpi_hosts/authentications/index.tsx +++ b/x-pack/plugins/security_solution/public/hosts/containers/kpi_hosts/authentications/index.tsx @@ -19,7 +19,7 @@ import { import { ESTermQuery } from '../../../../../common/typed_json'; import * as i18n from './translations'; -import { AbortError } from '../../../../../../../../src/plugins/data/common'; +import { AbortError } from '../../../../../../../../src/plugins/kibana_utils/common'; import { getInspectResponse } from '../../../../helpers'; import { InspectResponse } from '../../../../types'; diff --git a/x-pack/plugins/security_solution/public/hosts/containers/kpi_hosts/hosts/index.tsx b/x-pack/plugins/security_solution/public/hosts/containers/kpi_hosts/hosts/index.tsx index 13d9bf368fc3d..ff4539fd379ed 100644 --- a/x-pack/plugins/security_solution/public/hosts/containers/kpi_hosts/hosts/index.tsx +++ b/x-pack/plugins/security_solution/public/hosts/containers/kpi_hosts/hosts/index.tsx @@ -19,7 +19,7 @@ import { import { ESTermQuery } from '../../../../../common/typed_json'; import * as i18n from './translations'; -import { AbortError } from '../../../../../../../../src/plugins/data/common'; +import { AbortError } from '../../../../../../../../src/plugins/kibana_utils/common'; import { getInspectResponse } from '../../../../helpers'; import { InspectResponse } from '../../../../types'; diff --git a/x-pack/plugins/security_solution/public/hosts/containers/kpi_hosts/unique_ips/index.tsx b/x-pack/plugins/security_solution/public/hosts/containers/kpi_hosts/unique_ips/index.tsx index fb1d0e05dd2a0..906a1d2716513 100644 --- a/x-pack/plugins/security_solution/public/hosts/containers/kpi_hosts/unique_ips/index.tsx +++ b/x-pack/plugins/security_solution/public/hosts/containers/kpi_hosts/unique_ips/index.tsx @@ -19,7 +19,7 @@ import { import { ESTermQuery } from '../../../../../common/typed_json'; import * as i18n from './translations'; -import { AbortError } from '../../../../../../../../src/plugins/data/common'; +import { AbortError } from '../../../../../../../../src/plugins/kibana_utils/common'; import { getInspectResponse } from '../../../../helpers'; import { InspectResponse } from '../../../../types'; diff --git a/x-pack/plugins/security_solution/public/hosts/containers/uncommon_processes/index.tsx b/x-pack/plugins/security_solution/public/hosts/containers/uncommon_processes/index.tsx index ec792a6cad075..821b2895ac3f9 100644 --- a/x-pack/plugins/security_solution/public/hosts/containers/uncommon_processes/index.tsx +++ b/x-pack/plugins/security_solution/public/hosts/containers/uncommon_processes/index.tsx @@ -9,11 +9,8 @@ import { noop } from 'lodash/fp'; import { useCallback, useEffect, useRef, useState } from 'react'; import { useSelector } from 'react-redux'; -import { - AbortError, - isCompleteResponse, - isErrorResponse, -} from '../../../../../../../src/plugins/data/common'; +import { isCompleteResponse, isErrorResponse } from '../../../../../../../src/plugins/data/common'; +import { AbortError } from '../../../../../../../src/plugins/kibana_utils/common'; import { inputsModel, State } from '../../../common/store'; import { useKibana } from '../../../common/lib/kibana'; diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/action.ts b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/action.ts index dce135dd213b3..37a61b4adf020 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/action.ts +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/action.ts @@ -11,7 +11,7 @@ import { } from '../../../../../common/endpoint/types'; import { ServerApiError } from '../../../../common/types'; import { GetPolicyListResponse } from '../../policy/types'; -import { GetPackagesResponse } from '../../../../../../ingest_manager/common'; +import { GetPackagesResponse } from '../../../../../../fleet/common'; import { EndpointState } from '../types'; import { IIndexPattern } from '../../../../../../../../src/plugins/data/public'; diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts index 80b2d2b0192f8..a78bd5fde3216 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts @@ -26,7 +26,7 @@ import { sendGetAgentPolicyList, sendGetFleetAgentsWithEndpoint, } from '../../policy/store/policy_list/services/ingest'; -import { AGENT_POLICY_SAVED_OBJECT_TYPE } from '../../../../../../ingest_manager/common'; +import { AGENT_POLICY_SAVED_OBJECT_TYPE } from '../../../../../../fleet/common'; import { metadataCurrentIndexPattern } from '../../../../../common/endpoint/constants'; import { IIndexPattern, Query } from '../../../../../../../../src/plugins/data/public'; diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/mock_endpoint_result_list.ts b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/mock_endpoint_result_list.ts index cd8ebb4d0ec50..5b14b7d658965 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/mock_endpoint_result_list.ts +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/mock_endpoint_result_list.ts @@ -25,7 +25,7 @@ import { GetAgentPoliciesResponseItem, GetPackagesResponse, GetAgentsResponse, -} from '../../../../../../ingest_manager/common/types/rest_spec'; +} from '../../../../../../fleet/common/types/rest_spec'; import { GetPolicyListResponse } from '../../policy/types'; const generator = new EndpointDocGenerator('seed'); diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/types.ts b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/types.ts index e3e2dc7b55a5e..ec22c522c3d0a 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/types.ts +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/types.ts @@ -14,7 +14,7 @@ import { MetadataQueryStrategyVersions, } from '../../../../common/endpoint/types'; import { ServerApiError } from '../../../common/types'; -import { GetPackagesResponse } from '../../../../../ingest_manager/common'; +import { GetPackagesResponse } from '../../../../../fleet/common'; import { IIndexPattern } from '../../../../../../../src/plugins/data/public'; export interface EndpointState { diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/endpoint_details.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/endpoint_details.tsx index c0763a21f0947..dd7475361b950 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/endpoint_details.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/endpoint_details.tsx @@ -29,7 +29,7 @@ import { LinkToApp } from '../../../../../common/components/endpoint/link_to_app import { getEndpointDetailsPath } from '../../../../common/routing'; import { SecurityPageName } from '../../../../../app/types'; import { useFormatUrl } from '../../../../../common/components/link_to'; -import { AgentDetailsReassignPolicyAction } from '../../../../../../../ingest_manager/public'; +import { AgentDetailsReassignPolicyAction } from '../../../../../../../fleet/public'; import { EndpointPolicyLink } from '../components/endpoint_policy_link'; const HostIds = styled(EuiListGroupItem)` diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx index c5d3c3c25313d..670e8dc965ad9 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx @@ -51,7 +51,7 @@ import { CreatePackagePolicyRouteState, AgentPolicyDetailsDeployAgentAction, pagePathGetters, -} from '../../../../../../ingest_manager/public'; +} from '../../../../../../fleet/public'; import { SecurityPageName } from '../../../../app/types'; import { getEndpointListPath, getEndpointDetailsPath } from '../../../common/routing'; import { useFormatUrl } from '../../../../common/components/link_to'; diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/action.ts b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/action.ts index f729dfbd9a29a..f5a219bce4a6b 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/action.ts +++ b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/action.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { GetAgentStatusResponse } from '../../../../../../../ingest_manager/common/types/rest_spec'; +import { GetAgentStatusResponse } from '../../../../../../../fleet/common/types/rest_spec'; import { PolicyData, UIPolicyConfig } from '../../../../../../common/endpoint/types'; import { ServerApiError } from '../../../../../common/types'; import { PolicyDetailsState } from '../../types'; diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_list/action.ts b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_list/action.ts index 562cd6807f68a..cfd053948922b 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_list/action.ts +++ b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_list/action.ts @@ -6,10 +6,7 @@ import { PolicyData } from '../../../../../../common/endpoint/types'; import { ServerApiError } from '../../../../../common/types'; -import { - GetAgentStatusResponse, - GetPackagesResponse, -} from '../../../../../../../ingest_manager/common'; +import { GetAgentStatusResponse, GetPackagesResponse } from '../../../../../../../fleet/common'; interface ServerReturnedPolicyListData { type: 'serverReturnedPolicyListData'; diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_list/index.test.ts b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_list/index.test.ts index 03e65bd6f43cb..524c44406bd33 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_list/index.test.ts +++ b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_list/index.test.ts @@ -8,7 +8,7 @@ import { PolicyListState } from '../../types'; import { Store, applyMiddleware, createStore } from 'redux'; import { coreMock } from '../../../../../../../../../src/core/public/mocks'; -import { PACKAGE_POLICY_SAVED_OBJECT_TYPE } from '../../../../../../../ingest_manager/common'; +import { PACKAGE_POLICY_SAVED_OBJECT_TYPE } from '../../../../../../../fleet/common'; import { policyListReducer } from './reducer'; import { policyListMiddlewareFactory } from './middleware'; diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_list/middleware.ts b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_list/middleware.ts index fddd242e092ad..e57eb0e32e516 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_list/middleware.ts +++ b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_list/middleware.ts @@ -18,7 +18,7 @@ import { DeletePackagePoliciesResponse, DeletePackagePoliciesRequest, GetAgentStatusResponse, -} from '../../../../../../../ingest_manager/common'; +} from '../../../../../../../fleet/common'; export const policyListMiddlewareFactory: ImmutableMiddlewareFactory = ( coreStart diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_list/services/ingest.test.ts b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_list/services/ingest.test.ts index 00e7b0ca51ecf..43a12868368c5 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_list/services/ingest.test.ts +++ b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_list/services/ingest.test.ts @@ -11,7 +11,7 @@ import { sendGetEndpointSpecificPackagePolicies, } from './ingest'; import { httpServiceMock } from '../../../../../../../../../../src/core/public/mocks'; -import { PACKAGE_POLICY_SAVED_OBJECT_TYPE } from '../../../../../../../../ingest_manager/common'; +import { PACKAGE_POLICY_SAVED_OBJECT_TYPE } from '../../../../../../../../fleet/common'; import { policyListApiPathHandlers } from '../test_mock_utils'; describe('ingest service', () => { diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_list/services/ingest.ts b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_list/services/ingest.ts index 204dfe437815e..a241f8d1c4556 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_list/services/ingest.ts +++ b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_list/services/ingest.ts @@ -15,7 +15,7 @@ import { GetPackagesResponse, GetAgentPoliciesRequest, GetAgentPoliciesResponse, -} from '../../../../../../../../ingest_manager/common'; +} from '../../../../../../../../fleet/common'; import { GetPolicyListResponse, GetPolicyResponse, UpdatePolicyResponse } from '../../../types'; import { NewPolicyData } from '../../../../../../../common/endpoint/types'; diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_list/test_mock_utils.ts b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_list/test_mock_utils.ts index 1093aed0608d5..3c8b1f913c868 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_list/test_mock_utils.ts +++ b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_list/test_mock_utils.ts @@ -8,7 +8,7 @@ import { HttpStart } from 'kibana/public'; import { INGEST_API_EPM_PACKAGES, INGEST_API_PACKAGE_POLICIES } from './services/ingest'; import { EndpointDocGenerator } from '../../../../../../common/endpoint/generate_data'; import { GetPolicyListResponse } from '../../types'; -import { GetPackagesResponse } from '../../../../../../../ingest_manager/common'; +import { GetPackagesResponse } from '../../../../../../../fleet/common'; const generator = new EndpointDocGenerator('policy-list'); diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/types.ts b/x-pack/plugins/security_solution/public/management/pages/policy/types.ts index c7d426da05508..152caff3714b0 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/types.ts +++ b/x-pack/plugins/security_solution/public/management/pages/policy/types.ts @@ -18,7 +18,7 @@ import { GetPackagePoliciesResponse, GetPackagesResponse, UpdatePackagePolicyResponse, -} from '../../../../../ingest_manager/common'; +} from '../../../../../fleet/common'; /** * Policy list store state diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/configure_package_policy.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/configure_package_policy.tsx index 05e77c57ae52b..0be5f119e5eff 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/configure_package_policy.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/configure_package_policy.tsx @@ -23,7 +23,7 @@ import { CustomConfigurePackagePolicyContent, CustomConfigurePackagePolicyProps, pagePathGetters, -} from '../../../../../../../ingest_manager/public'; +} from '../../../../../../../fleet/public'; import { getPolicyDetailPath, getTrustedAppsListPath } from '../../../../common/routing'; import { MANAGEMENT_APP_ID } from '../../../../common/constants'; import { diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_list.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_list.tsx index 78226a858bfeb..274032eea0c5d 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_list.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_list.tsx @@ -46,7 +46,7 @@ import { SecurityPageName } from '../../../../app/types'; import { useFormatUrl } from '../../../../common/components/link_to'; import { getPolicyDetailPath, getPoliciesPath } from '../../../common/routing'; import { useNavigateToAppEventHandler } from '../../../../common/hooks/endpoint/use_navigate_to_app_event_handler'; -import { CreatePackagePolicyRouteState } from '../../../../../../ingest_manager/public'; +import { CreatePackagePolicyRouteState } from '../../../../../../fleet/public'; import { MANAGEMENT_APP_ID } from '../../../common/constants'; import { AdministrationListPage } from '../../../components/administration_list_page'; diff --git a/x-pack/plugins/security_solution/public/network/containers/details/index.tsx b/x-pack/plugins/security_solution/public/network/containers/details/index.tsx index 2d5ed093ca1e4..8a80d073d4beb 100644 --- a/x-pack/plugins/security_solution/public/network/containers/details/index.tsx +++ b/x-pack/plugins/security_solution/public/network/containers/details/index.tsx @@ -18,11 +18,8 @@ import { NetworkDetailsRequestOptions, NetworkDetailsStrategyResponse, } from '../../../../common/search_strategy'; -import { - AbortError, - isCompleteResponse, - isErrorResponse, -} from '../../../../../../../src/plugins/data/common'; +import { isCompleteResponse, isErrorResponse } from '../../../../../../../src/plugins/data/common'; +import { AbortError } from '../../../../../../../src/plugins/kibana_utils/common'; import * as i18n from './translations'; import { getInspectResponse } from '../../../helpers'; import { InspectResponse } from '../../../types'; diff --git a/x-pack/plugins/security_solution/public/network/containers/kpi_network/dns/index.tsx b/x-pack/plugins/security_solution/public/network/containers/kpi_network/dns/index.tsx index 65f10a03cf13d..39868af2ae14d 100644 --- a/x-pack/plugins/security_solution/public/network/containers/kpi_network/dns/index.tsx +++ b/x-pack/plugins/security_solution/public/network/containers/kpi_network/dns/index.tsx @@ -20,10 +20,10 @@ import { ESTermQuery } from '../../../../../common/typed_json'; import * as i18n from './translations'; import { - AbortError, isCompleteResponse, isErrorResponse, } from '../../../../../../../../src/plugins/data/common'; +import { AbortError } from '../../../../../../../../src/plugins/kibana_utils/common'; import { getInspectResponse } from '../../../../helpers'; import { InspectResponse } from '../../../../types'; diff --git a/x-pack/plugins/security_solution/public/network/containers/kpi_network/network_events/index.tsx b/x-pack/plugins/security_solution/public/network/containers/kpi_network/network_events/index.tsx index a8f1a7abe2d44..3a4ce40fb8b80 100644 --- a/x-pack/plugins/security_solution/public/network/containers/kpi_network/network_events/index.tsx +++ b/x-pack/plugins/security_solution/public/network/containers/kpi_network/network_events/index.tsx @@ -20,10 +20,10 @@ import { ESTermQuery } from '../../../../../common/typed_json'; import * as i18n from './translations'; import { - AbortError, isCompleteResponse, isErrorResponse, } from '../../../../../../../../src/plugins/data/common'; +import { AbortError } from '../../../../../../../../src/plugins/kibana_utils/common'; import { getInspectResponse } from '../../../../helpers'; import { InspectResponse } from '../../../../types'; diff --git a/x-pack/plugins/security_solution/public/network/containers/kpi_network/tls_handshakes/index.tsx b/x-pack/plugins/security_solution/public/network/containers/kpi_network/tls_handshakes/index.tsx index 61861de9c0033..40cd04207b2d9 100644 --- a/x-pack/plugins/security_solution/public/network/containers/kpi_network/tls_handshakes/index.tsx +++ b/x-pack/plugins/security_solution/public/network/containers/kpi_network/tls_handshakes/index.tsx @@ -20,10 +20,10 @@ import { ESTermQuery } from '../../../../../common/typed_json'; import * as i18n from './translations'; import { - AbortError, isCompleteResponse, isErrorResponse, } from '../../../../../../../../src/plugins/data/common'; +import { AbortError } from '../../../../../../../../src/plugins/kibana_utils/common'; import { getInspectResponse } from '../../../../helpers'; import { InspectResponse } from '../../../../types'; diff --git a/x-pack/plugins/security_solution/public/network/containers/kpi_network/unique_flows/index.tsx b/x-pack/plugins/security_solution/public/network/containers/kpi_network/unique_flows/index.tsx index 594fc2a2adcfa..a2a64d0770558 100644 --- a/x-pack/plugins/security_solution/public/network/containers/kpi_network/unique_flows/index.tsx +++ b/x-pack/plugins/security_solution/public/network/containers/kpi_network/unique_flows/index.tsx @@ -20,10 +20,10 @@ import { ESTermQuery } from '../../../../../common/typed_json'; import * as i18n from './translations'; import { - AbortError, isCompleteResponse, isErrorResponse, } from '../../../../../../../../src/plugins/data/common'; +import { AbortError } from '../../../../../../../../src/plugins/kibana_utils/common'; import { getInspectResponse } from '../../../../helpers'; import { InspectResponse } from '../../../../types'; diff --git a/x-pack/plugins/security_solution/public/network/containers/kpi_network/unique_private_ips/index.tsx b/x-pack/plugins/security_solution/public/network/containers/kpi_network/unique_private_ips/index.tsx index 8484f1388caac..d183eb243e158 100644 --- a/x-pack/plugins/security_solution/public/network/containers/kpi_network/unique_private_ips/index.tsx +++ b/x-pack/plugins/security_solution/public/network/containers/kpi_network/unique_private_ips/index.tsx @@ -21,10 +21,10 @@ import { ESTermQuery } from '../../../../../common/typed_json'; import * as i18n from './translations'; import { - AbortError, isCompleteResponse, isErrorResponse, } from '../../../../../../../../src/plugins/data/common'; +import { AbortError } from '../../../../../../../../src/plugins/kibana_utils/common'; import { getInspectResponse } from '../../../../helpers'; import { InspectResponse } from '../../../../types'; diff --git a/x-pack/plugins/security_solution/public/network/containers/network_dns/index.tsx b/x-pack/plugins/security_solution/public/network/containers/network_dns/index.tsx index 92a8f8c49dfc6..fc00f8866ed2e 100644 --- a/x-pack/plugins/security_solution/public/network/containers/network_dns/index.tsx +++ b/x-pack/plugins/security_solution/public/network/containers/network_dns/index.tsx @@ -22,11 +22,8 @@ import { NetworkDnsStrategyResponse, MatrixOverOrdinalHistogramData, } from '../../../../common/search_strategy/security_solution/network'; -import { - AbortError, - isCompleteResponse, - isErrorResponse, -} from '../../../../../../../src/plugins/data/common'; +import { isCompleteResponse, isErrorResponse } from '../../../../../../../src/plugins/data/common'; +import { AbortError } from '../../../../../../../src/plugins/kibana_utils/common'; import * as i18n from './translations'; import { getInspectResponse } from '../../../helpers'; import { InspectResponse } from '../../../types'; diff --git a/x-pack/plugins/security_solution/public/network/containers/network_http/index.tsx b/x-pack/plugins/security_solution/public/network/containers/network_http/index.tsx index e4fa68b75999f..8edb760429a7c 100644 --- a/x-pack/plugins/security_solution/public/network/containers/network_http/index.tsx +++ b/x-pack/plugins/security_solution/public/network/containers/network_http/index.tsx @@ -23,11 +23,8 @@ import { NetworkHttpStrategyResponse, SortField, } from '../../../../common/search_strategy'; -import { - AbortError, - isCompleteResponse, - isErrorResponse, -} from '../../../../../../../src/plugins/data/common'; +import { isCompleteResponse, isErrorResponse } from '../../../../../../../src/plugins/data/common'; +import { AbortError } from '../../../../../../../src/plugins/kibana_utils/common'; import * as i18n from './translations'; import { InspectResponse } from '../../../types'; import { getInspectResponse } from '../../../helpers'; diff --git a/x-pack/plugins/security_solution/public/network/containers/network_top_countries/index.tsx b/x-pack/plugins/security_solution/public/network/containers/network_top_countries/index.tsx index 4b0ea2b82855b..0676d5976e211 100644 --- a/x-pack/plugins/security_solution/public/network/containers/network_top_countries/index.tsx +++ b/x-pack/plugins/security_solution/public/network/containers/network_top_countries/index.tsx @@ -23,11 +23,8 @@ import { NetworkTopCountriesStrategyResponse, PageInfoPaginated, } from '../../../../common/search_strategy'; -import { - AbortError, - isCompleteResponse, - isErrorResponse, -} from '../../../../../../../src/plugins/data/common'; +import { isCompleteResponse, isErrorResponse } from '../../../../../../../src/plugins/data/common'; +import { AbortError } from '../../../../../../../src/plugins/kibana_utils/common'; import { getInspectResponse } from '../../../helpers'; import { InspectResponse } from '../../../types'; import * as i18n from './translations'; diff --git a/x-pack/plugins/security_solution/public/network/containers/network_top_n_flow/index.tsx b/x-pack/plugins/security_solution/public/network/containers/network_top_n_flow/index.tsx index 342fbbf67be4d..49ff6016900a5 100644 --- a/x-pack/plugins/security_solution/public/network/containers/network_top_n_flow/index.tsx +++ b/x-pack/plugins/security_solution/public/network/containers/network_top_n_flow/index.tsx @@ -23,11 +23,8 @@ import { NetworkTopNFlowStrategyResponse, PageInfoPaginated, } from '../../../../common/search_strategy'; -import { - AbortError, - isCompleteResponse, - isErrorResponse, -} from '../../../../../../../src/plugins/data/common'; +import { isCompleteResponse, isErrorResponse } from '../../../../../../../src/plugins/data/common'; +import { AbortError } from '../../../../../../../src/plugins/kibana_utils/common'; import { getInspectResponse } from '../../../helpers'; import { InspectResponse } from '../../../types'; import * as i18n from './translations'; diff --git a/x-pack/plugins/security_solution/public/network/containers/tls/index.tsx b/x-pack/plugins/security_solution/public/network/containers/tls/index.tsx index 336aaec1d4bc9..8abd91186465a 100644 --- a/x-pack/plugins/security_solution/public/network/containers/tls/index.tsx +++ b/x-pack/plugins/security_solution/public/network/containers/tls/index.tsx @@ -21,11 +21,8 @@ import { NetworkTlsRequestOptions, NetworkTlsStrategyResponse, } from '../../../../common/search_strategy/security_solution/network'; -import { - AbortError, - isCompleteResponse, - isErrorResponse, -} from '../../../../../../../src/plugins/data/common'; +import { isCompleteResponse, isErrorResponse } from '../../../../../../../src/plugins/data/common'; +import { AbortError } from '../../../../../../../src/plugins/kibana_utils/common'; import * as i18n from './translations'; import { getInspectResponse } from '../../../helpers'; diff --git a/x-pack/plugins/security_solution/public/network/containers/users/index.tsx b/x-pack/plugins/security_solution/public/network/containers/users/index.tsx index 8f21a23417aae..75f28773b89f6 100644 --- a/x-pack/plugins/security_solution/public/network/containers/users/index.tsx +++ b/x-pack/plugins/security_solution/public/network/containers/users/index.tsx @@ -23,11 +23,8 @@ import { NetworkUsersRequestOptions, NetworkUsersStrategyResponse, } from '../../../../common/search_strategy/security_solution/network'; -import { - AbortError, - isCompleteResponse, - isErrorResponse, -} from '../../../../../../../src/plugins/data/common'; +import { isCompleteResponse, isErrorResponse } from '../../../../../../../src/plugins/data/common'; +import { AbortError } from '../../../../../../../src/plugins/kibana_utils/common'; import * as i18n from './translations'; import { getInspectResponse } from '../../../helpers'; import { InspectResponse } from '../../../types'; diff --git a/x-pack/plugins/security_solution/public/overview/containers/overview_host/index.tsx b/x-pack/plugins/security_solution/public/overview/containers/overview_host/index.tsx index 3c59ff7ba36c2..edf68750e2fdd 100644 --- a/x-pack/plugins/security_solution/public/overview/containers/overview_host/index.tsx +++ b/x-pack/plugins/security_solution/public/overview/containers/overview_host/index.tsx @@ -17,11 +17,8 @@ import { useKibana } from '../../../common/lib/kibana'; import { inputsModel } from '../../../common/store/inputs'; import { createFilter } from '../../../common/containers/helpers'; import { ESQuery } from '../../../../common/typed_json'; -import { - AbortError, - isCompleteResponse, - isErrorResponse, -} from '../../../../../../../src/plugins/data/common'; +import { isCompleteResponse, isErrorResponse } from '../../../../../../../src/plugins/data/common'; +import { AbortError } from '../../../../../../../src/plugins/kibana_utils/common'; import { getInspectResponse } from '../../../helpers'; import { InspectResponse } from '../../../types'; import * as i18n from './translations'; diff --git a/x-pack/plugins/security_solution/public/overview/containers/overview_network/index.tsx b/x-pack/plugins/security_solution/public/overview/containers/overview_network/index.tsx index 7f659db70277f..c414276c1a615 100644 --- a/x-pack/plugins/security_solution/public/overview/containers/overview_network/index.tsx +++ b/x-pack/plugins/security_solution/public/overview/containers/overview_network/index.tsx @@ -17,11 +17,8 @@ import { useKibana } from '../../../common/lib/kibana'; import { inputsModel } from '../../../common/store/inputs'; import { createFilter } from '../../../common/containers/helpers'; import { ESQuery } from '../../../../common/typed_json'; -import { - AbortError, - isCompleteResponse, - isErrorResponse, -} from '../../../../../../../src/plugins/data/common'; +import { isCompleteResponse, isErrorResponse } from '../../../../../../../src/plugins/data/common'; +import { AbortError } from '../../../../../../../src/plugins/kibana_utils/common'; import { getInspectResponse } from '../../../helpers'; import { InspectResponse } from '../../../types'; import * as i18n from './translations'; diff --git a/x-pack/plugins/security_solution/public/types.ts b/x-pack/plugins/security_solution/public/types.ts index d72a8b9261587..5e8400c574235 100644 --- a/x-pack/plugins/security_solution/public/types.ts +++ b/x-pack/plugins/security_solution/public/types.ts @@ -15,7 +15,7 @@ import { UiActionsStart } from '../../../../src/plugins/ui_actions/public'; import { UsageCollectionSetup } from '../../../../src/plugins/usage_collection/public'; import { TelemetryManagementSectionPluginSetup } from '../../../../src/plugins/telemetry_management_section/public'; import { Storage } from '../../../../src/plugins/kibana_utils/public'; -import { IngestManagerStart } from '../../ingest_manager/public'; +import { IngestManagerStart } from '../../fleet/public'; import { PluginStart as ListsPluginStart } from '../../lists/public'; import { TriggersAndActionsUIPublicPluginSetup as TriggersActionsSetup, diff --git a/x-pack/plugins/security_solution/scripts/endpoint/resolver_generator_script.ts b/x-pack/plugins/security_solution/scripts/endpoint/resolver_generator_script.ts index 3796c3f62d0ee..9ad094086b632 100644 --- a/x-pack/plugins/security_solution/scripts/endpoint/resolver_generator_script.ts +++ b/x-pack/plugins/security_solution/scripts/endpoint/resolver_generator_script.ts @@ -11,11 +11,11 @@ import { KbnClient, ToolingLog } from '@kbn/dev-utils'; import { AxiosResponse } from 'axios'; import { indexHostsAndAlerts } from '../../common/endpoint/index_data'; import { ANCESTRY_LIMIT, EndpointDocGenerator } from '../../common/endpoint/generate_data'; -import { AGENTS_SETUP_API_ROUTES, SETUP_API_ROUTE } from '../../../ingest_manager/common/constants'; +import { AGENTS_SETUP_API_ROUTES, SETUP_API_ROUTE } from '../../../fleet/common/constants'; import { CreateFleetSetupResponse, PostIngestSetupResponse, -} from '../../../ingest_manager/common/types/rest_spec'; +} from '../../../fleet/common/types/rest_spec'; import { KbnClientWithApiKeySupport } from './kbn_client_with_api_key_support'; main(); diff --git a/x-pack/plugins/security_solution/server/endpoint/endpoint_app_context_services.ts b/x-pack/plugins/security_solution/server/endpoint/endpoint_app_context_services.ts index 2cc8245e521bf..c7f49f479583e 100644 --- a/x-pack/plugins/security_solution/server/endpoint/endpoint_app_context_services.ts +++ b/x-pack/plugins/security_solution/server/endpoint/endpoint_app_context_services.ts @@ -10,11 +10,7 @@ import { SavedObjectsClientContract, } from 'src/core/server'; import { SecurityPluginSetup } from '../../../security/server'; -import { - AgentService, - IngestManagerStartContract, - PackageService, -} from '../../../ingest_manager/server'; +import { AgentService, IngestManagerStartContract, PackageService } from '../../../fleet/server'; import { PluginStartContract as AlertsPluginStartContract } from '../../../alerts/server'; import { getPackagePolicyCreateCallback } from './ingest_integration'; import { ManifestManager } from './services/artifacts'; @@ -24,7 +20,7 @@ import { metadataQueryStrategyV1, metadataQueryStrategyV2, } from './routes/metadata/support/query_strategies'; -import { ElasticsearchAssetType } from '../../../ingest_manager/common/types/models'; +import { ElasticsearchAssetType } from '../../../fleet/common/types/models'; import { metadataTransformPrefix } from '../../common/endpoint/constants'; import { AppClientFactory } from '../client'; import { ConfigType } from '../config'; diff --git a/x-pack/plugins/security_solution/server/endpoint/ingest_integration.test.ts b/x-pack/plugins/security_solution/server/endpoint/ingest_integration.test.ts index 1db3e9984284d..321d67a441f6d 100644 --- a/x-pack/plugins/security_solution/server/endpoint/ingest_integration.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/ingest_integration.test.ts @@ -5,7 +5,7 @@ */ import { httpServerMock, loggingSystemMock } from 'src/core/server/mocks'; -import { createNewPackagePolicyMock } from '../../../ingest_manager/common/mocks'; +import { createNewPackagePolicyMock } from '../../../fleet/common/mocks'; import { factory as policyConfigFactory } from '../../common/endpoint/models/policy_config'; import { getManifestManagerMock, diff --git a/x-pack/plugins/security_solution/server/endpoint/ingest_integration.ts b/x-pack/plugins/security_solution/server/endpoint/ingest_integration.ts index 279603cd621c8..3c94bdc63b0fb 100644 --- a/x-pack/plugins/security_solution/server/endpoint/ingest_integration.ts +++ b/x-pack/plugins/security_solution/server/endpoint/ingest_integration.ts @@ -6,9 +6,9 @@ import { PluginStartContract as AlertsStartContract } from '../../../alerts/server'; import { SecurityPluginSetup } from '../../../security/server'; -import { ExternalCallback } from '../../../ingest_manager/server'; +import { ExternalCallback } from '../../../fleet/server'; import { KibanaRequest, Logger, RequestHandlerContext } from '../../../../../src/core/server'; -import { NewPackagePolicy } from '../../../ingest_manager/common/types/models'; +import { NewPackagePolicy } from '../../../fleet/common/types/models'; import { factory as policyConfigFactory } from '../../common/endpoint/models/policy_config'; import { NewPolicyData } from '../../common/endpoint/types'; import { ManifestManager } from './services/artifacts'; diff --git a/x-pack/plugins/security_solution/server/endpoint/lib/artifacts/mocks.ts b/x-pack/plugins/security_solution/server/endpoint/lib/artifacts/mocks.ts index cdfbb551940e1..44b1d5fefe4e1 100644 --- a/x-pack/plugins/security_solution/server/endpoint/lib/artifacts/mocks.ts +++ b/x-pack/plugins/security_solution/server/endpoint/lib/artifacts/mocks.ts @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { PackagePolicy } from '../../../../../ingest_manager/common'; -import { createPackagePolicyMock } from '../../../../../ingest_manager/common/mocks'; +import { PackagePolicy } from '../../../../../fleet/common'; +import { createPackagePolicyMock } from '../../../../../fleet/common/mocks'; import { InternalArtifactCompleteSchema } from '../../schemas/artifacts'; import { getInternalArtifactMock, diff --git a/x-pack/plugins/security_solution/server/endpoint/mocks.ts b/x-pack/plugins/security_solution/server/endpoint/mocks.ts index 98b971a00710d..588404fd516d0 100644 --- a/x-pack/plugins/security_solution/server/endpoint/mocks.ts +++ b/x-pack/plugins/security_solution/server/endpoint/mocks.ts @@ -14,8 +14,8 @@ import { IngestManagerStartContract, ExternalCallback, PackageService, -} from '../../../ingest_manager/server'; -import { createPackagePolicyServiceMock } from '../../../ingest_manager/server/mocks'; +} from '../../../fleet/server'; +import { createPackagePolicyServiceMock } from '../../../fleet/server/mocks'; import { AppClientFactory } from '../client'; import { createMockConfig } from '../lib/detection_engine/routes/__mocks__'; import { diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/artifacts/download_exception_list.ts b/x-pack/plugins/security_solution/server/endpoint/routes/artifacts/download_exception_list.ts index d825841f1e257..401f7e97470be 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/artifacts/download_exception_list.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/artifacts/download_exception_list.ts @@ -12,7 +12,7 @@ import { } from 'src/core/server'; import LRU from 'lru-cache'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { authenticateAgentWithAccessToken } from '../../../../../ingest_manager/server/services/agents/authenticate'; +import { authenticateAgentWithAccessToken } from '../../../../../fleet/server/services/agents/authenticate'; import { LIMITED_CONCURRENCY_ENDPOINT_ROUTE_TAG } from '../../../../common/endpoint/constants'; import { buildRouteValidation } from '../../../utils/build_validation/route_validation'; import { ArtifactConstants } from '../../lib/artifacts'; diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/handlers.ts b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/handlers.ts index 194f0a1c2e7c5..f2011e99565c8 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/handlers.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/handlers.ts @@ -15,7 +15,7 @@ import { MetadataQueryStrategyVersions, } from '../../../../common/endpoint/types'; import { getESQueryHostMetadataByID, kibanaRequestToMetadataListESQuery } from './query_builders'; -import { Agent, AgentStatus } from '../../../../../ingest_manager/common/types/models'; +import { Agent, AgentStatus } from '../../../../../fleet/common/types/models'; import { EndpointAppContext, HostListQueryResult } from '../../types'; import { GetMetadataListRequestSchema, GetMetadataRequestSchema } from './index'; import { findAllUnenrolledAgentIds } from './support/unenroll'; diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/metadata.test.ts b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/metadata.test.ts index 227a3e6fd9657..46a4363936b3d 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/metadata.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/metadata.test.ts @@ -39,9 +39,9 @@ import { Agent, ElasticsearchAssetType, EsAssetReference, -} from '../../../../../ingest_manager/common/types/models'; +} from '../../../../../fleet/common/types/models'; import { createV1SearchResponse, createV2SearchResponse } from './support/test_support'; -import { PackageService } from '../../../../../ingest_manager/server/services'; +import { PackageService } from '../../../../../fleet/server/services'; import { metadataTransformPrefix } from '../../../../common/endpoint/constants'; describe('test endpoint route', () => { diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/metadata_v1.test.ts b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/metadata_v1.test.ts index 568917c804733..26f216f0474c2 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/metadata_v1.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/metadata_v1.test.ts @@ -35,9 +35,9 @@ import { import { EndpointAppContextService } from '../../endpoint_app_context_services'; import { createMockConfig } from '../../../lib/detection_engine/routes/__mocks__'; import { EndpointDocGenerator } from '../../../../common/endpoint/generate_data'; -import { Agent, EsAssetReference } from '../../../../../ingest_manager/common/types/models'; +import { Agent, EsAssetReference } from '../../../../../fleet/common/types/models'; import { createV1SearchResponse } from './support/test_support'; -import { PackageService } from '../../../../../ingest_manager/server/services'; +import { PackageService } from '../../../../../fleet/server/services'; describe('test endpoint route v1', () => { let routerMock: jest.Mocked; diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/support/agent_status.test.ts b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/support/agent_status.test.ts index a4b6b0750ec10..ed3c48ed6c677 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/support/agent_status.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/support/agent_status.test.ts @@ -7,10 +7,10 @@ import { SavedObjectsClientContract } from 'kibana/server'; import { findAgentIDsByStatus } from './agent_status'; import { savedObjectsClientMock } from '../../../../../../../../src/core/server/mocks'; -import { AgentService } from '../../../../../../ingest_manager/server/services'; +import { AgentService } from '../../../../../../fleet/server/services'; import { createMockAgentService } from '../../../mocks'; -import { Agent } from '../../../../../../ingest_manager/common/types/models'; -import { AgentStatusKueryHelper } from '../../../../../../ingest_manager/common/services'; +import { Agent } from '../../../../../../fleet/common/types/models'; +import { AgentStatusKueryHelper } from '../../../../../../fleet/common/services'; describe('test filtering endpoint hosts by agent status', () => { let mockSavedObjectClient: jest.Mocked; diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/support/agent_status.ts b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/support/agent_status.ts index 86f6d1a9a65e2..395b05c0887e9 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/support/agent_status.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/support/agent_status.ts @@ -5,9 +5,9 @@ */ import { SavedObjectsClientContract } from 'kibana/server'; -import { AgentService } from '../../../../../../ingest_manager/server'; -import { AgentStatusKueryHelper } from '../../../../../../ingest_manager/common/services'; -import { Agent } from '../../../../../../ingest_manager/common/types/models'; +import { AgentService } from '../../../../../../fleet/server'; +import { AgentStatusKueryHelper } from '../../../../../../fleet/common/services'; +import { Agent } from '../../../../../../fleet/common/types/models'; import { HostStatus } from '../../../../../common/endpoint/types'; const STATUS_QUERY_MAP = new Map([ diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/support/unenroll.test.ts b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/support/unenroll.test.ts index 30c8f14287cae..cd273f785033c 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/support/unenroll.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/support/unenroll.test.ts @@ -7,9 +7,9 @@ import { SavedObjectsClientContract } from 'kibana/server'; import { findAllUnenrolledAgentIds } from './unenroll'; import { savedObjectsClientMock } from '../../../../../../../../src/core/server/mocks'; -import { AgentService } from '../../../../../../ingest_manager/server/services'; +import { AgentService } from '../../../../../../fleet/server/services'; import { createMockAgentService } from '../../../mocks'; -import { Agent } from '../../../../../../ingest_manager/common/types/models'; +import { Agent } from '../../../../../../fleet/common/types/models'; describe('test find all unenrolled Agent id', () => { let mockSavedObjectClient: jest.Mocked; diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/support/unenroll.ts b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/support/unenroll.ts index ca2ced177ab33..1abea86c1a495 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/support/unenroll.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/support/unenroll.ts @@ -5,8 +5,8 @@ */ import { SavedObjectsClientContract } from 'kibana/server'; -import { AgentService } from '../../../../../../ingest_manager/server'; -import { Agent } from '../../../../../../ingest_manager/common/types/models'; +import { AgentService } from '../../../../../../fleet/server'; +import { Agent } from '../../../../../../fleet/common/types/models'; export async function findAllUnenrolledAgentIds( agentService: AgentService, diff --git a/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.mock.ts b/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.mock.ts index 27dd38047e7c3..353bfb6b0f16e 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.mock.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.mock.ts @@ -6,8 +6,8 @@ import { savedObjectsClientMock, loggingSystemMock } from 'src/core/server/mocks'; import { Logger } from 'src/core/server'; -import { PackagePolicyServiceInterface } from '../../../../../../ingest_manager/server'; -import { createPackagePolicyServiceMock } from '../../../../../../ingest_manager/server/mocks'; +import { PackagePolicyServiceInterface } from '../../../../../../fleet/server'; +import { createPackagePolicyServiceMock } from '../../../../../../fleet/server/mocks'; import { ExceptionListClient } from '../../../../../../lists/server'; import { listMock } from '../../../../../../lists/server/mocks'; import LRU from 'lru-cache'; diff --git a/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.test.ts b/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.test.ts index 40b408166b17f..f5a27b7602e8b 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.test.ts @@ -6,7 +6,7 @@ import { inflateSync } from 'zlib'; import { savedObjectsClientMock } from 'src/core/server/mocks'; -import { createPackagePolicyServiceMock } from '../../../../../../ingest_manager/server/mocks'; +import { createPackagePolicyServiceMock } from '../../../../../../fleet/server/mocks'; import { ArtifactConstants, ManifestConstants, isCompleteArtifact } from '../../../lib/artifacts'; import { getManifestManagerMock, ManifestManagerMockType } from './manifest_manager.mock'; diff --git a/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts b/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts index f9836c7ecdc30..9f45f39a392f6 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts @@ -6,7 +6,7 @@ import semver from 'semver'; import { Logger, SavedObjectsClientContract } from 'src/core/server'; import LRU from 'lru-cache'; -import { PackagePolicyServiceInterface } from '../../../../../../ingest_manager/server'; +import { PackagePolicyServiceInterface } from '../../../../../../fleet/server'; import { ExceptionListClient } from '../../../../../../lists/server'; import { ManifestSchemaVersion } from '../../../../../common/endpoint/schema/common'; import { manifestDispatchSchema } from '../../../../../common/endpoint/schema/manifest'; diff --git a/x-pack/plugins/security_solution/server/lib/hosts/elasticsearch_adapter.test.ts b/x-pack/plugins/security_solution/server/lib/hosts/elasticsearch_adapter.test.ts index 6abff93d6cd5c..53e3da62f4e35 100644 --- a/x-pack/plugins/security_solution/server/lib/hosts/elasticsearch_adapter.test.ts +++ b/x-pack/plugins/security_solution/server/lib/hosts/elasticsearch_adapter.test.ts @@ -34,8 +34,8 @@ import { createMockEndpointAppContextServiceStartContract, createMockPackageService, } from '../../endpoint/mocks'; -import { PackageService } from '../../../../ingest_manager/server/services'; -import { ElasticsearchAssetType } from '../../../../ingest_manager/common/types/models'; +import { PackageService } from '../../../../fleet/server/services'; +import { ElasticsearchAssetType } from '../../../../fleet/common/types/models'; jest.mock('./query.hosts.dsl', () => { return { diff --git a/x-pack/plugins/security_solution/server/plugin.ts b/x-pack/plugins/security_solution/server/plugin.ts index 43f87a0c69ab3..d8faa2436bf55 100644 --- a/x-pack/plugins/security_solution/server/plugin.ts +++ b/x-pack/plugins/security_solution/server/plugin.ts @@ -34,7 +34,7 @@ import { ListPluginSetup } from '../../lists/server'; import { EncryptedSavedObjectsPluginSetup as EncryptedSavedObjectsSetup } from '../../encrypted_saved_objects/server'; import { SpacesPluginSetup as SpacesSetup } from '../../spaces/server'; import { LicensingPluginSetup } from '../../licensing/server'; -import { IngestManagerStartContract, ExternalCallback } from '../../ingest_manager/server'; +import { IngestManagerStartContract, ExternalCallback } from '../../fleet/server'; import { TaskManagerSetupContract, TaskManagerStartContract } from '../../task_manager/server'; import { initServer } from './init_server'; import { compose } from './lib/compose/kibana'; diff --git a/x-pack/plugins/security_solution/server/usage/endpoints/endpoint.mocks.ts b/x-pack/plugins/security_solution/server/usage/endpoints/endpoint.mocks.ts index d5e1d21b7772b..b8858100171f9 100644 --- a/x-pack/plugins/security_solution/server/usage/endpoints/endpoint.mocks.ts +++ b/x-pack/plugins/security_solution/server/usage/endpoints/endpoint.mocks.ts @@ -4,12 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ import { SavedObjectsFindResponse } from 'src/core/server'; -import { AgentEventSOAttributes } from './../../../../ingest_manager/common/types/models/agent'; +import { AgentEventSOAttributes } from './../../../../fleet/common/types/models/agent'; import { AGENT_SAVED_OBJECT_TYPE, AGENT_EVENT_SAVED_OBJECT_TYPE, -} from '../../../../ingest_manager/common/constants/agent'; -import { Agent } from '../../../../ingest_manager/common'; +} from '../../../../fleet/common/constants/agent'; +import { Agent } from '../../../../fleet/common'; import { FLEET_ENDPOINT_PACKAGE_CONSTANT } from './fleet_saved_objects'; const testAgentId = 'testAgentId'; diff --git a/x-pack/plugins/security_solution/server/usage/endpoints/endpoint.test.ts b/x-pack/plugins/security_solution/server/usage/endpoints/endpoint.test.ts index e2f7a3be6d80a..6d4b97564c90e 100644 --- a/x-pack/plugins/security_solution/server/usage/endpoints/endpoint.test.ts +++ b/x-pack/plugins/security_solution/server/usage/endpoints/endpoint.test.ts @@ -12,8 +12,8 @@ import { MockOSVersion, } from './endpoint.mocks'; import { ISavedObjectsRepository, SavedObjectsFindResponse } from 'src/core/server'; -import { AgentEventSOAttributes } from '../../../../ingest_manager/common/types/models/agent'; -import { Agent } from '../../../../ingest_manager/common'; +import { AgentEventSOAttributes } from '../../../../fleet/common/types/models/agent'; +import { Agent } from '../../../../fleet/common'; import * as endpointTelemetry from './index'; import * as fleetSavedObjects from './fleet_saved_objects'; diff --git a/x-pack/plugins/security_solution/server/usage/endpoints/fleet_saved_objects.ts b/x-pack/plugins/security_solution/server/usage/endpoints/fleet_saved_objects.ts index 405339aaf25e2..7ffb53dcf2a3f 100644 --- a/x-pack/plugins/security_solution/server/usage/endpoints/fleet_saved_objects.ts +++ b/x-pack/plugins/security_solution/server/usage/endpoints/fleet_saved_objects.ts @@ -5,12 +5,12 @@ */ import { ISavedObjectsRepository } from 'src/core/server'; -import { AgentEventSOAttributes } from './../../../../ingest_manager/common/types/models/agent'; +import { AgentEventSOAttributes } from './../../../../fleet/common/types/models/agent'; import { AGENT_SAVED_OBJECT_TYPE, AGENT_EVENT_SAVED_OBJECT_TYPE, -} from './../../../../ingest_manager/common/constants/agent'; -import { Agent, defaultPackages as FleetDefaultPackages } from '../../../../ingest_manager/common'; +} from './../../../../fleet/common/constants/agent'; +import { Agent, defaultPackages as FleetDefaultPackages } from '../../../../fleet/common'; export const FLEET_ENDPOINT_PACKAGE_CONSTANT = FleetDefaultPackages.Endpoint; diff --git a/x-pack/plugins/security_solution/server/usage/endpoints/index.ts b/x-pack/plugins/security_solution/server/usage/endpoints/index.ts index f1ce9d3ad6ff3..f1642c52ef405 100644 --- a/x-pack/plugins/security_solution/server/usage/endpoints/index.ts +++ b/x-pack/plugins/security_solution/server/usage/endpoints/index.ts @@ -6,8 +6,8 @@ import { cloneDeep } from 'lodash'; import { ISavedObjectsRepository } from 'src/core/server'; import { SavedObject } from './../../../../../../src/core/types/saved_objects'; -import { Agent, NewAgentEvent } from './../../../../ingest_manager/common/types/models/agent'; -import { AgentMetadata } from '../../../../ingest_manager/common/types/models/agent'; +import { Agent, NewAgentEvent } from './../../../../fleet/common/types/models/agent'; +import { AgentMetadata } from '../../../../fleet/common/types/models/agent'; import { getFleetSavedObjectsMetadata, getLatestFleetEndpointEvent } from './fleet_saved_objects'; export interface AgentOSMetadataTelemetry { diff --git a/x-pack/plugins/spaces/public/management/spaces_grid/__snapshots__/spaces_grid_pages.test.tsx.snap b/x-pack/plugins/spaces/public/management/spaces_grid/__snapshots__/spaces_grid_pages.test.tsx.snap index f4f92a26028ad..497b13642b81b 100644 --- a/x-pack/plugins/spaces/public/management/spaces_grid/__snapshots__/spaces_grid_pages.test.tsx.snap +++ b/x-pack/plugins/spaces/public/management/spaces_grid/__snapshots__/spaces_grid_pages.test.tsx.snap @@ -112,6 +112,7 @@ exports[`SpacesGridPage renders as expected 1`] = ` } pagination={true} responsive={true} + rowHeader="name" search={ Object { "box": Object { @@ -120,6 +121,7 @@ exports[`SpacesGridPage renders as expected 1`] = ` } } sorting={true} + tableCaption="Kibana spaces" tableLayout="fixed" /> diff --git a/x-pack/plugins/spaces/public/management/spaces_grid/spaces_grid_page.tsx b/x-pack/plugins/spaces/public/management/spaces_grid/spaces_grid_page.tsx index b40f34273d99f..68c4a4ff02b94 100644 --- a/x-pack/plugins/spaces/public/management/spaces_grid/spaces_grid_page.tsx +++ b/x-pack/plugins/spaces/public/management/spaces_grid/spaces_grid_page.tsx @@ -110,6 +110,10 @@ export class SpacesGridPage extends Component { { date: '2020-01-01T00:00:00.000Z', group: '[group]', value: 42, + function: 'count > 4', }; const context = addMessages({ name: '[alert-name]' }, base, params); expect(context.title).toMatchInlineSnapshot( @@ -53,6 +54,7 @@ describe('ActionContext', () => { date: '2020-01-01T00:00:00.000Z', group: '[group]', value: 42, + function: 'avg([aggField]) > 4.2', }; const context = addMessages({ name: '[alert-name]' }, base, params); expect(context.title).toMatchInlineSnapshot( @@ -80,6 +82,7 @@ describe('ActionContext', () => { date: '2020-01-01T00:00:00.000Z', group: '[group]', value: 4, + function: 'count between 4,5', }; const context = addMessages({ name: '[alert-name]' }, base, params); expect(context.title).toMatchInlineSnapshot( diff --git a/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/action_context.ts b/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/action_context.ts index 5135e31e9322c..9bb0df9d07fd4 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/action_context.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/action_context.ts @@ -27,6 +27,8 @@ export interface BaseActionContext extends AlertInstanceContext { date: string; // the value that met the threshold value: number; + // the function that is used + function: string; } export function addMessages( @@ -42,9 +44,6 @@ export function addMessages( }, }); - const agg = params.aggField ? `${params.aggType}(${params.aggField})` : `${params.aggType}`; - const humanFn = `${agg} ${params.thresholdComparator} ${params.threshold.join(',')}`; - const window = `${params.timeWindowSize}${params.timeWindowUnit}`; const message = i18n.translate( 'xpack.stackAlerts.indexThreshold.alertTypeContextMessageDescription', @@ -55,7 +54,7 @@ export function addMessages( name: alertInfo.name, group: baseContext.group, value: baseContext.value, - function: humanFn, + function: baseContext.function, window, date: baseContext.date, }, diff --git a/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/alert_type.test.ts b/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/alert_type.test.ts index 2f0cf3cbbcd16..d75f3af22ab06 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/alert_type.test.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/alert_type.test.ts @@ -46,6 +46,10 @@ describe('alertType', () => { "description": "The value that exceeded the threshold.", "name": "value", }, + Object { + "description": "A string describing the threshold comparator and threshold", + "name": "function", + }, ], "params": Array [ Object { diff --git a/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/alert_type.ts b/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/alert_type.ts index 2a1ed429b7fe1..e0a9cd981dac0 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/alert_type.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/alert_type.ts @@ -83,6 +83,13 @@ export function getAlertType(service: Service): AlertType { return { @@ -107,6 +114,7 @@ export function getAlertType(service: Service): AlertType void; + setActionGroupIdByIndex?: (group: string, index: number) => void; setAlertProperty: (actions: AlertAction[]) => void; setActionParamsProperty: (key: string, value: any, index: number) => void; http: HttpSetup; - actionTypeRegistry: TypeRegistry; - toastNotifications: Pick< - ToastsApi, - 'get$' | 'add' | 'remove' | 'addSuccess' | 'addWarning' | 'addDanger' | 'addError' - >; + actionTypeRegistry: ActionTypeRegistryContract; + toastNotifications: ToastsSetup; + docLinks: DocLinksStart; actionTypes?: ActionType[]; messageVariables?: ActionVariable[]; defaultActionMessage?: string; - consumer: string; + capabilities: ApplicationStart['capabilities']; } ``` @@ -1339,17 +1339,20 @@ interface ActionAccordionFormProps { |Property|Description| |---|---| |actions|List of actions comes from alert.actions property.| -|defaultActionGroupId|Default action group id to which each new action will belong to.| +|defaultActionGroupId|Default action group id to which each new action will belong by default.| +|actionGroups|Optional. List of action groups to which new action can be assigned. The RunWhen field is only displayed when these action groups are specified| |setActionIdByIndex|Function for changing action 'id' by the proper index in alert.actions array.| +|setActionGroupIdByIndex|Function for changing action 'group' by the proper index in alert.actions array.| |setAlertProperty|Function for changing alert property 'actions'. Used when deleting action from the array to reset it.| |setActionParamsProperty|Function for changing action key/value property by index in alert.actions array.| |http|HttpSetup needed for executing API calls.| |actionTypeRegistry|Registry for action types.| -|toastNotifications|Toast messages.| +|toastNotifications|Toast messages Plugin Setup Contract.| +|docLinks|Documentation links Plugin Start Contract.| |actionTypes|Optional property, which allowes to define a list of available actions specific for a current plugin.| |actionTypes|Optional property, which allowes to define a list of variables for action 'message' property.| |defaultActionMessage|Optional property, which allowes to define a message value for action with 'message' property.| -|consumer|Name of the plugin that creates an action.| +|capabilities|Kibana core's Capabilities ApplicationStart['capabilities'].| AlertsContextProvider value options: diff --git a/x-pack/plugins/triggers_actions_ui/public/application/app.tsx b/x-pack/plugins/triggers_actions_ui/public/application/app.tsx index fc48a8e977c7d..5c1e0aa0100e8 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/app.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/app.tsx @@ -16,8 +16,8 @@ import { CoreStart, ScopedHistory, } from 'kibana/public'; -import { Section, routeToAlertDetails } from './constants'; import { KibanaFeature } from '../../../features/common'; +import { Section, routeToAlertDetails } from './constants'; import { AppContextProvider } from './app_context'; import { ActionTypeRegistryContract, AlertTypeRegistryContract } from '../types'; import { ChartsPluginStart } from '../../../../../src/plugins/charts/public'; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_alert_types/threshold/index.ts b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_alert_types/threshold/index.ts index d105e2c510bcd..a5b2fbb37e838 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_alert_types/threshold/index.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_alert_types/threshold/index.ts @@ -5,7 +5,6 @@ */ import { lazy } from 'react'; import { i18n } from '@kbn/i18n'; - import { AlertTypeModel } from '../../../../types'; import { validateExpression } from './validation'; import { IndexThresholdAlertParams } from './types'; @@ -26,6 +25,12 @@ export function getAlertType(): AlertTypeModel import('./expression')), validate: validateExpression, + defaultActionMessage: i18n.translate( + 'xpack.triggersActionsUI.components.builtinAlertTypes.threshold.alertDefaultActionMessage', + { + defaultMessage: `alert \\{\\{alertName\\}\\} group \\{\\{context.group\\}\\} value \\{\\{context.value\\}\\} exceeded threshold \\{\\{context.function\\}\\} over \\{\\{params.timeWindowSize\\}\\}\\{\\{params.timeWindowUnit\\}\\} on \\{\\{context.date\\}\\}`, + } + ), requiresAppContext: false, }; } diff --git a/x-pack/plugins/triggers_actions_ui/public/application/context/alerts_context.tsx b/x-pack/plugins/triggers_actions_ui/public/application/context/alerts_context.tsx index a4293f94268ba..0b2f777d13f25 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/context/alerts_context.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/context/alerts_context.tsx @@ -18,6 +18,7 @@ import { DataPublicPluginStartUi, IndexPatternsContract, } from 'src/plugins/data/public'; +import { KibanaFeature } from '../../../../features/common'; import { AlertTypeRegistryContract, ActionTypeRegistryContract } from '../../types'; export interface AlertsContextValue> { @@ -34,6 +35,7 @@ export interface AlertsContextValue> { metadata?: MetaData; dataUi?: DataPublicPluginStartUi; dataIndexPatterns?: IndexPatternsContract; + kibanaFeatures?: KibanaFeature[]; } const AlertsContext = createContext(null as any); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/check_action_type_enabled.scss b/x-pack/plugins/triggers_actions_ui/public/application/lib/check_action_type_enabled.scss index 24dbb865742d8..bb622829e997a 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/check_action_type_enabled.scss +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/check_action_type_enabled.scss @@ -3,9 +3,15 @@ } .actAccordionActionForm { - .euiCard { - box-shadow: none; - } + background-color: $euiColorLightestShade; +} + +.actAccordionActionForm .euiCard { + box-shadow: none; +} + +.actAccordionActionForm__button { + padding: $euiSizeM; } .actConnectorsListGrid { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_form.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_form.test.tsx index 7c718e8248e41..94452e70e6bfa 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_form.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_form.test.tsx @@ -6,7 +6,6 @@ import React, { Fragment, lazy } from 'react'; import { mountWithIntl, nextTick } from 'test_utils/enzyme_helpers'; import { coreMock } from '../../../../../../../src/core/public/mocks'; -import { ReactWrapper } from 'enzyme'; import { act } from 'react-dom/test-utils'; import { actionTypeRegistryMock } from '../../action_type_registry.mock'; import { ValidationResult, Alert, AlertAction } from '../../../types'; @@ -112,8 +111,6 @@ describe('action_form', () => { }; describe('action_form in alert', () => { - let wrapper: ReactWrapper; - async function setup(customActions?: AlertAction[]) { const { loadAllActions } = jest.requireMock('../../lib/action_connector_api'); loadAllActions.mockResolvedValueOnce([ @@ -217,7 +214,7 @@ describe('action_form', () => { mutedInstanceIds: [], } as unknown) as Alert; - wrapper = mountWithIntl( + const wrapper = mountWithIntl( { setActionIdByIndex={(id: string, index: number) => { initialAlert.actions[index].id = id; }} + actionGroups={[{ id: 'default', name: 'Default' }]} + setActionGroupIdByIndex={(group: string, index: number) => { + initialAlert.actions[index].group = group; + }} setAlertProperty={(_updatedActions: AlertAction[]) => {}} setActionParamsProperty={(key: string, value: any, index: number) => (initialAlert.actions[index] = { ...initialAlert.actions[index], [key]: value }) @@ -297,10 +298,12 @@ describe('action_form', () => { await nextTick(); wrapper.update(); }); + + return wrapper; } it('renders available action cards', async () => { - await setup(); + const wrapper = await setup(); const actionOption = wrapper.find( `[data-test-subj="${actionType.id}-ActionTypeSelectOption"]` ); @@ -314,7 +317,7 @@ describe('action_form', () => { }); it('does not render action types disabled by config', async () => { - await setup(); + const wrapper = await setup(); const actionOption = wrapper.find( '[data-test-subj="disabled-by-config-ActionTypeSelectOption"]' ); @@ -322,52 +325,72 @@ describe('action_form', () => { }); it('render action types which is preconfigured only (disabled by config and with preconfigured connectors)', async () => { - await setup(); + const wrapper = await setup(); const actionOption = wrapper.find('[data-test-subj="preconfigured-ActionTypeSelectOption"]'); expect(actionOption.exists()).toBeTruthy(); }); + it('renders available action groups for the selected action type', async () => { + const wrapper = await setup(); + const actionOption = wrapper.find( + `[data-test-subj="${actionType.id}-ActionTypeSelectOption"]` + ); + actionOption.first().simulate('click'); + const actionGroupsSelect = wrapper.find( + `[data-test-subj="addNewActionConnectorActionGroup-0"]` + ); + expect((actionGroupsSelect.first().props() as any).options).toMatchInlineSnapshot(` + Array [ + Object { + "data-test-subj": "addNewActionConnectorActionGroup-0-option-default", + "inputDisplay": "Default", + "value": "default", + }, + ] + `); + }); + it('renders available connectors for the selected action type', async () => { - await setup(); + const wrapper = await setup(); const actionOption = wrapper.find( `[data-test-subj="${actionType.id}-ActionTypeSelectOption"]` ); actionOption.first().simulate('click'); const combobox = wrapper.find(`[data-test-subj="selectActionConnector-${actionType.id}"]`); expect((combobox.first().props() as any).options).toMatchInlineSnapshot(` - Array [ - Object { - "id": "test", - "key": "test", - "label": "Test connector ", - }, - Object { - "id": "test2", - "key": "test2", - "label": "Test connector 2 (preconfigured)", - }, - ] - `); + Array [ + Object { + "id": "test", + "key": "test", + "label": "Test connector ", + }, + Object { + "id": "test2", + "key": "test2", + "label": "Test connector 2 (preconfigured)", + }, + ] + `); }); it('renders only preconfigured connectors for the selected preconfigured action type', async () => { - await setup(); + const wrapper = await setup(); const actionOption = wrapper.find('[data-test-subj="preconfigured-ActionTypeSelectOption"]'); actionOption.first().simulate('click'); const combobox = wrapper.find('[data-test-subj="selectActionConnector-preconfigured"]'); expect((combobox.first().props() as any).options).toMatchInlineSnapshot(` - Array [ - Object { - "id": "test3", - "key": "test3", - "label": "Preconfigured Only (preconfigured)", - }, - ] - `); + Array [ + Object { + "id": "test3", + "key": "test3", + "label": "Preconfigured Only (preconfigured)", + }, + ] + `); }); it('does not render "Add connector" button for preconfigured only action type', async () => { - await setup(); + const wrapper = await setup(); const actionOption = wrapper.find('[data-test-subj="preconfigured-ActionTypeSelectOption"]'); actionOption.first().simulate('click'); const preconfigPannel = wrapper.find('[data-test-subj="alertActionAccordion-default"]'); @@ -378,7 +401,7 @@ describe('action_form', () => { }); it('renders action types disabled by license', async () => { - await setup(); + const wrapper = await setup(); const actionOption = wrapper.find( '[data-test-subj="disabled-by-license-ActionTypeSelectOption"]' ); @@ -391,7 +414,7 @@ describe('action_form', () => { }); it(`shouldn't render action types without params component`, async () => { - await setup(); + const wrapper = await setup(); const actionOption = wrapper.find( `[data-test-subj="${actionTypeWithoutParams.id}-ActionTypeSelectOption"]` ); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_form.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_form.tsx index 74432157f5659..3a7341afe3e07 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_form.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_form.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { Fragment, Suspense, useState, useEffect } from 'react'; +import React, { Fragment, useState, useEffect, useCallback } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { @@ -14,25 +14,13 @@ import { EuiIcon, EuiTitle, EuiSpacer, - EuiFormRow, - EuiComboBox, EuiKeyPadMenuItem, - EuiAccordion, - EuiButtonIcon, - EuiEmptyPrompt, - EuiButtonEmpty, EuiToolTip, - EuiIconTip, EuiLink, - EuiCallOut, - EuiHorizontalRule, - EuiText, - EuiLoadingSpinner, } from '@elastic/eui'; import { HttpSetup, ToastsSetup, ApplicationStart, DocLinksStart } from 'kibana/public'; import { loadActionTypes, loadAllActions as loadConnectors } from '../../lib/action_connector_api'; import { - IErrorObject, ActionTypeModel, ActionTypeRegistryContract, AlertAction, @@ -43,15 +31,19 @@ import { } from '../../../types'; import { SectionLoading } from '../../components/section_loading'; import { ConnectorAddModal } from './connector_add_modal'; +import { ActionTypeForm, ActionTypeFormProps } from './action_type_form'; +import { AddConnectorInline } from './connector_add_inline'; import { actionTypeCompare } from '../../lib/action_type_compare'; import { checkActionFormActionTypeEnabled } from '../../lib/check_action_type_enabled'; import { VIEW_LICENSE_OPTIONS_LINK, DEFAULT_HIDDEN_ACTION_TYPES } from '../../../common/constants'; -import { hasSaveActionsCapability } from '../../lib/capabilities'; +import { ActionGroup } from '../../../../../alerts/common'; -interface ActionAccordionFormProps { +export interface ActionAccordionFormProps { actions: AlertAction[]; defaultActionGroupId: string; + actionGroups?: ActionGroup[]; setActionIdByIndex: (id: string, index: number) => void; + setActionGroupIdByIndex?: (group: string, index: number) => void; setAlertProperty: (actions: AlertAction[]) => void; setActionParamsProperty: (key: string, value: any, index: number) => void; http: HttpSetup; @@ -74,7 +66,9 @@ interface ActiveActionConnectorState { export const ActionForm = ({ actions, defaultActionGroupId, + actionGroups, setActionIdByIndex, + setActionGroupIdByIndex, setAlertProperty, setActionParamsProperty, http, @@ -88,8 +82,6 @@ export const ActionForm = ({ capabilities, docLinks, }: ActionAccordionFormProps) => { - const canSave = hasSaveActionsCapability(capabilities); - const [addModalVisible, setAddModalVisibility] = useState(false); const [activeActionItem, setActiveActionItem] = useState( undefined @@ -101,6 +93,10 @@ export const ActionForm = ({ const [actionTypesIndex, setActionTypesIndex] = useState(undefined); const [emptyActionsIds, setEmptyActionsIds] = useState([]); + const closeAddConnectorModal = useCallback(() => setAddModalVisibility(false), [ + setAddModalVisibility, + ]); + // load action types useEffect(() => { (async () => { @@ -183,359 +179,6 @@ export const ActionForm = ({ // eslint-disable-next-line react-hooks/exhaustive-deps }, [actions, connectors]); - const preconfiguredMessage = i18n.translate( - 'xpack.triggersActionsUI.sections.actionForm.preconfiguredTitleMessage', - { - defaultMessage: '(preconfigured)', - } - ); - - const getSelectedOptions = (actionItemId: string) => { - const selectedConnector = connectors.find((connector) => connector.id === actionItemId); - if ( - !selectedConnector || - // if selected connector is not preconfigured and action type is for preconfiguration only, - // do not show regular connectors of this type - (actionTypesIndex && - !actionTypesIndex[selectedConnector.actionTypeId].enabledInConfig && - !selectedConnector.isPreconfigured) - ) { - return []; - } - const optionTitle = `${selectedConnector.name} ${ - selectedConnector.isPreconfigured ? preconfiguredMessage : '' - }`; - return [ - { - label: optionTitle, - value: optionTitle, - id: actionItemId, - 'data-test-subj': 'itemActionConnector', - }, - ]; - }; - - const getActionTypeForm = ( - actionItem: AlertAction, - actionConnector: ActionConnector, - actionParamsErrors: { - errors: IErrorObject; - }, - index: number - ) => { - if (!actionTypesIndex) { - return null; - } - - const actionType = actionTypesIndex[actionItem.actionTypeId]; - - const optionsList = connectors - .filter( - (connectorItem) => - connectorItem.actionTypeId === actionItem.actionTypeId && - // include only enabled by config connectors or preconfigured - (actionType.enabledInConfig || connectorItem.isPreconfigured) - ) - .map(({ name, id, isPreconfigured }) => ({ - label: `${name} ${isPreconfigured ? preconfiguredMessage : ''}`, - key: id, - id, - })); - const actionTypeRegistered = actionTypeRegistry.get(actionConnector.actionTypeId); - if (!actionTypeRegistered || actionItem.group !== defaultActionGroupId) return null; - const ParamsFieldsComponent = actionTypeRegistered.actionParamsFields; - const checkEnabledResult = checkActionFormActionTypeEnabled( - actionTypesIndex[actionConnector.actionTypeId], - connectors.filter((connector) => connector.isPreconfigured) - ); - - const accordionContent = checkEnabledResult.isEnabled ? ( - - - - - } - labelAppend={ - canSave && - actionTypesIndex && - actionTypesIndex[actionConnector.actionTypeId].enabledInConfig ? ( - { - setActiveActionItem({ actionTypeId: actionItem.actionTypeId, index }); - setAddModalVisibility(true); - }} - > - - - ) : null - } - > - { - setActionIdByIndex(selectedOptions[0].id ?? '', index); - }} - isClearable={false} - /> - - - - - {ParamsFieldsComponent ? ( - - - - - - } - > - - - ) : null} - - ) : ( - checkEnabledResult.messageCard - ); - - return ( - - - - - - - -
- - - - - - {checkEnabledResult.isEnabled === false && ( - - - - )} - - -
-
-
- - } - extraAction={ - { - const updatedActions = actions.filter( - (_item: AlertAction, i: number) => i !== index - ); - setAlertProperty(updatedActions); - setIsAddActionPanelOpen( - updatedActions.filter((item: AlertAction) => item.id !== actionItem.id).length === - 0 - ); - setActiveActionItem(undefined); - }} - /> - } - paddingSize="l" - > - {accordionContent} -
- -
- ); - }; - - const getAddConnectorsForm = (actionItem: AlertAction, index: number) => { - const actionTypeName = actionTypesIndex - ? actionTypesIndex[actionItem.actionTypeId].name - : actionItem.actionTypeId; - const actionTypeRegistered = actionTypeRegistry.get(actionItem.actionTypeId); - if (!actionTypeRegistered || actionItem.group !== defaultActionGroupId) return null; - - const noConnectorsLabel = ( - - ); - return ( - - - - - - - -
- -
-
-
- - } - extraAction={ - { - const updatedActions = actions.filter( - (_item: AlertAction, i: number) => i !== index - ); - setAlertProperty(updatedActions); - setIsAddActionPanelOpen( - updatedActions.filter((item: AlertAction) => item.id !== actionItem.id).length === - 0 - ); - setActiveActionItem(undefined); - }} - /> - } - paddingSize="l" - > - {canSave ? ( - actionItem.id === emptyId) ? ( - noConnectorsLabel - ) : ( - - ) - } - actions={[ - { - setActiveActionItem({ actionTypeId: actionItem.actionTypeId, index }); - setAddModalVisibility(true); - }} - > - - , - ]} - /> - ) : ( - -

- -

-
- )} -
- -
- ); - }; - function addActionType(actionTypeModel: ActionTypeModel) { if (!defaultActionGroupId) { toastNotifications!.addDanger({ @@ -628,116 +271,172 @@ export const ActionForm = ({ }); } - const alertActionsList = actions.map((actionItem: AlertAction, index: number) => { - const actionConnector = connectors.find((field) => field.id === actionItem.id); - // connectors doesn't exists - if (!actionConnector) { - return getAddConnectorsForm(actionItem, index); - } - - const actionErrors: { errors: IErrorObject } = actionTypeRegistry - .get(actionItem.actionTypeId) - ?.validateParams(actionItem.params); - - return getActionTypeForm(actionItem, actionConnector, actionErrors, index); - }); - - return ( + return isLoadingConnectors ? ( + + + + ) : ( - {isLoadingConnectors ? ( - + +

- - ) : ( - - -

- + + + {actionTypesIndex && + actions.map((actionItem: AlertAction, index: number) => { + const actionConnector = connectors.find((field) => field.id === actionItem.id); + // connectors doesn't exists + if (!actionConnector) { + return ( + { + const updatedActions = actions.filter( + (_item: AlertAction, i: number) => i !== index + ); + setAlertProperty(updatedActions); + setIsAddActionPanelOpen( + updatedActions.filter((item: AlertAction) => item.id !== actionItem.id) + .length === 0 + ); + setActiveActionItem(undefined); + }} + onAddConnector={() => { + setActiveActionItem({ actionTypeId: actionItem.actionTypeId, index }); + setAddModalVisibility(true); + }} /> -

-
- - {alertActionsList} - {isAddActionPanelOpen === false ? ( -
- - - - setIsAddActionPanelOpen(true)} - > - - - - -
- ) : null} - {isAddActionPanelOpen ? ( - - - - -
+ ); + } + + const actionParamsErrors: ActionTypeFormProps['actionParamsErrors'] = actionTypeRegistry + .get(actionItem.actionTypeId) + ?.validateParams(actionItem.params); + + return ( + { + setActiveActionItem({ actionTypeId: actionItem.actionTypeId, index }); + setAddModalVisibility(true); + }} + onConnectorSelected={(id: string) => { + setActionIdByIndex(id, index); + }} + onDeleteAction={() => { + const updatedActions = actions.filter( + (_item: AlertAction, i: number) => i !== index + ); + setAlertProperty(updatedActions); + setIsAddActionPanelOpen( + updatedActions.filter((item: AlertAction) => item.id !== actionItem.id).length === + 0 + ); + setActiveActionItem(undefined); + }} + /> + ); + })} + + {isAddActionPanelOpen ? ( + + + + +
+ +
+
+
+ {hasDisabledByLicenseActionTypes && ( + + +
+ -
-
-
- {hasDisabledByLicenseActionTypes && ( - - -
- - - -
-
-
- )} -
- - - {isLoadingActionTypes ? ( - - - - ) : ( - actionTypeNodes - )} - -
- ) : null} + +
+
+
+ )} +
+ + + {isLoadingActionTypes ? ( + + + + ) : ( + actionTypeNodes + )} +
+ ) : ( + + + setIsAddActionPanelOpen(true)} + > + + + + )} - {actionTypesIndex && activeActionItem ? ( + {actionTypesIndex && activeActionItem && addModalVisible ? ( { connectors.push(savedAction); setActionIdByIndex(savedAction.id, activeActionItem.index); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_type_form.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_type_form.tsx new file mode 100644 index 0000000000000..38468283b9c19 --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_type_form.tsx @@ -0,0 +1,339 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { Fragment, Suspense, useState } from 'react'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { + EuiFlexGroup, + EuiFlexItem, + EuiIcon, + EuiSpacer, + EuiFormRow, + EuiComboBox, + EuiAccordion, + EuiButtonIcon, + EuiButtonEmpty, + EuiIconTip, + EuiText, + EuiFormLabel, + EuiFormControlLayout, + EuiSuperSelect, + EuiLoadingSpinner, + EuiBadge, +} from '@elastic/eui'; +import { IErrorObject, AlertAction, ActionTypeIndex, ActionConnector } from '../../../types'; +import { checkActionFormActionTypeEnabled } from '../../lib/check_action_type_enabled'; +import { hasSaveActionsCapability } from '../../lib/capabilities'; +import { ActionAccordionFormProps } from './action_form'; + +export type ActionTypeFormProps = { + actionItem: AlertAction; + actionConnector: ActionConnector; + actionParamsErrors: { + errors: IErrorObject; + }; + index: number; + onAddConnector: () => void; + onConnectorSelected: (id: string) => void; + onDeleteAction: () => void; + setActionParamsProperty: (key: string, value: any, index: number) => void; + actionTypesIndex: ActionTypeIndex; + connectors: ActionConnector[]; +} & Pick< + ActionAccordionFormProps, + | 'defaultActionGroupId' + | 'actionGroups' + | 'setActionGroupIdByIndex' + | 'setActionParamsProperty' + | 'http' + | 'actionTypeRegistry' + | 'toastNotifications' + | 'docLinks' + | 'messageVariables' + | 'defaultActionMessage' + | 'capabilities' +>; + +const preconfiguredMessage = i18n.translate( + 'xpack.triggersActionsUI.sections.actionForm.preconfiguredTitleMessage', + { + defaultMessage: '(preconfigured)', + } +); + +export const ActionTypeForm = ({ + actionItem, + actionConnector, + actionParamsErrors, + index, + onAddConnector, + onConnectorSelected, + onDeleteAction, + setActionParamsProperty, + actionTypesIndex, + connectors, + http, + toastNotifications, + docLinks, + capabilities, + actionTypeRegistry, + defaultActionGroupId, + defaultActionMessage, + messageVariables, + actionGroups, + setActionGroupIdByIndex, +}: ActionTypeFormProps) => { + const [isOpen, setIsOpen] = useState(true); + + const canSave = hasSaveActionsCapability(capabilities); + const getSelectedOptions = (actionItemId: string) => { + const selectedConnector = connectors.find((connector) => connector.id === actionItemId); + if ( + !selectedConnector || + // if selected connector is not preconfigured and action type is for preconfiguration only, + // do not show regular connectors of this type + (actionTypesIndex && + !actionTypesIndex[selectedConnector.actionTypeId].enabledInConfig && + !selectedConnector.isPreconfigured) + ) { + return []; + } + const optionTitle = `${selectedConnector.name} ${ + selectedConnector.isPreconfigured ? preconfiguredMessage : '' + }`; + return [ + { + label: optionTitle, + value: optionTitle, + id: actionItemId, + 'data-test-subj': 'itemActionConnector', + }, + ]; + }; + + const actionType = actionTypesIndex[actionItem.actionTypeId]; + + const optionsList = connectors + .filter( + (connectorItem) => + connectorItem.actionTypeId === actionItem.actionTypeId && + // include only enabled by config connectors or preconfigured + (actionType.enabledInConfig || connectorItem.isPreconfigured) + ) + .map(({ name, id, isPreconfigured }) => ({ + label: `${name} ${isPreconfigured ? preconfiguredMessage : ''}`, + key: id, + id, + })); + const actionTypeRegistered = actionTypeRegistry.get(actionConnector.actionTypeId); + if (!actionTypeRegistered) return null; + + const ParamsFieldsComponent = actionTypeRegistered.actionParamsFields; + const checkEnabledResult = checkActionFormActionTypeEnabled( + actionTypesIndex[actionConnector.actionTypeId], + connectors.filter((connector) => connector.isPreconfigured) + ); + + const defaultActionGroup = actionGroups?.find(({ id }) => id === defaultActionGroupId); + const selectedActionGroup = + actionGroups?.find(({ id }) => id === actionItem.group) ?? defaultActionGroup; + + const accordionContent = checkEnabledResult.isEnabled ? ( + + {actionGroups && selectedActionGroup && setActionGroupIdByIndex && ( + + + + + + + } + > + ({ + value, + inputDisplay: name, + 'data-test-subj': `addNewActionConnectorActionGroup-${index}-option-${value}`, + }))} + valueOfSelected={selectedActionGroup.id} + onChange={(group) => { + setActionGroupIdByIndex(group, index); + }} + /> + + + + + + )} + + + + } + labelAppend={ + canSave && + actionTypesIndex && + actionTypesIndex[actionConnector.actionTypeId].enabledInConfig ? ( + + + + ) : null + } + > + { + onConnectorSelected(selectedOptions[0].id ?? ''); + }} + isClearable={false} + /> + + + + + {ParamsFieldsComponent ? ( + + + + + + } + > + + + ) : null} + + ) : ( + checkEnabledResult.messageCard + ); + + return ( + + + + + + + +
+ + + + + {selectedActionGroup && !isOpen && ( + + {selectedActionGroup.name} + + )} + + {checkEnabledResult.isEnabled === false && ( + + + + )} + + +
+
+
+ + } + extraAction={ + + } + > + {accordionContent} +
+ +
+ ); +}; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_inline.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_inline.tsx new file mode 100644 index 0000000000000..97baf4a36cb4c --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_inline.tsx @@ -0,0 +1,153 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { Fragment } from 'react'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { + EuiButton, + EuiFlexGroup, + EuiFlexItem, + EuiIcon, + EuiSpacer, + EuiAccordion, + EuiButtonIcon, + EuiEmptyPrompt, + EuiCallOut, + EuiText, +} from '@elastic/eui'; +import { AlertAction, ActionTypeIndex } from '../../../types'; +import { hasSaveActionsCapability } from '../../lib/capabilities'; +import { ActionAccordionFormProps } from './action_form'; + +type AddConnectorInFormProps = { + actionTypesIndex: ActionTypeIndex; + actionItem: AlertAction; + index: number; + onAddConnector: () => void; + onDeleteConnector: () => void; + emptyActionsIds: string[]; +} & Pick; + +export const AddConnectorInline = ({ + actionTypesIndex, + actionItem, + index, + onAddConnector, + onDeleteConnector, + actionTypeRegistry, + emptyActionsIds, + defaultActionGroupId, + capabilities, +}: AddConnectorInFormProps) => { + const canSave = hasSaveActionsCapability(capabilities); + + const actionTypeName = actionTypesIndex + ? actionTypesIndex[actionItem.actionTypeId].name + : actionItem.actionTypeId; + const actionTypeRegistered = actionTypeRegistry.get(actionItem.actionTypeId); + if (!actionTypeRegistered || actionItem.group !== defaultActionGroupId) return null; + + const noConnectorsLabel = ( + + ); + return ( + + + + + + + +
+ +
+
+
+ + } + extraAction={ + + } + paddingSize="l" + > + {canSave ? ( + actionItem.id === emptyId) ? ( + noConnectorsLabel + ) : ( + + ) + } + actions={[ + + + , + ]} + /> + ) : ( + +

+ +

+
+ )} +
+ +
+ ); +}; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_modal.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_modal.test.tsx index cba9eea3cf3f7..71a3936ed5055 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_modal.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_modal.test.tsx @@ -65,8 +65,7 @@ describe('connector_add_modal', () => { const wrapper = mountWithIntl( {}} + onClose={() => {}} actionType={actionType} http={deps!.http} actionTypeRegistry={deps!.actionTypeRegistry} diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_modal.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_modal.tsx index 13ec8395aa557..de27256bf566c 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_modal.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_modal.tsx @@ -32,8 +32,7 @@ import { interface ConnectorAddModalProps { actionType: ActionType; - addModalVisible: boolean; - setAddModalVisibility: React.Dispatch>; + onClose: () => void; postSaveEventHandler?: (savedAction: ActionConnector) => void; http: HttpSetup; actionTypeRegistry: ActionTypeRegistryContract; @@ -48,8 +47,7 @@ interface ConnectorAddModalProps { export const ConnectorAddModal = ({ actionType, - addModalVisible, - setAddModalVisibility, + onClose, postSaveEventHandler, http, toastNotifications, @@ -79,14 +77,11 @@ export const ConnectorAddModal = ({ >(undefined); const closeModal = useCallback(() => { - setAddModalVisibility(false); setConnector(initialConnector); setServerError(undefined); - }, [initialConnector, setAddModalVisibility]); + onClose(); + }, [initialConnector, onClose]); - if (!addModalVisible) { - return null; - } const actionTypeModel = actionTypeRegistry.get(actionType.id); const errors = { ...actionTypeModel?.validateConnector(connector).errors, diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_add.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_add.test.tsx index d66c5ba5121b8..4b5f8596501e1 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_add.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_add.test.tsx @@ -182,8 +182,6 @@ describe('alert_add', () => { wrapper.find('[data-test-subj="my-alert-type-SelectOption"]').first().simulate('click'); - expect(wrapper.contains('Metadata: some value. Fields: test.')).toBeTruthy(); - expect(wrapper.find('input#alertName').props().value).toBe(''); expect(wrapper.find('[data-test-subj="tagsComboBox"]').first().text()).toBe(''); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_form.scss b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_form.scss new file mode 100644 index 0000000000000..5d6ac684002fb --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_form.scss @@ -0,0 +1,4 @@ +.triggersActionsUI__alertTypeNodeHeading { + margin-left: $euiSizeS; + margin-right: $euiSizeS; +} diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_form.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_form.test.tsx index 4041f6f451a23..493b870a1a6d5 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_form.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_form.test.tsx @@ -187,7 +187,7 @@ describe('alert_form', () => { it('renders alert type description', async () => { await setup(); - wrapper.find('[data-test-subj="my-alert-type-SelectOption"]').first().simulate('click'); + wrapper.find('button[data-test-subj="my-alert-type-SelectOption"]').first().simulate('click'); const alertDescription = wrapper.find('[data-test-subj="alertDescription"]'); expect(alertDescription.exists()).toBeTruthy(); expect(alertDescription.first().text()).toContain('Alert when testing'); @@ -195,7 +195,7 @@ describe('alert_form', () => { it('renders alert type documentation link', async () => { await setup(); - wrapper.find('[data-test-subj="my-alert-type-SelectOption"]').first().simulate('click'); + wrapper.find('button[data-test-subj="my-alert-type-SelectOption"]').first().simulate('click'); const alertDocumentationLink = wrapper.find('[data-test-subj="alertDocumentationLink"]'); expect(alertDocumentationLink.exists()).toBeTruthy(); expect(alertDocumentationLink.first().prop('href')).toBe('https://localhost.local/docs'); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_form.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_form.tsx index 9a637ea750f81..213d1d7ad36df 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_form.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_form.tsx @@ -3,21 +3,21 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import React, { Fragment, useState, useEffect, Suspense } from 'react'; +import React, { Fragment, useState, useEffect, Suspense, useCallback } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiFlexGroup, EuiFlexItem, - EuiIcon, + EuiTextColor, EuiTitle, EuiForm, EuiSpacer, EuiFieldText, + EuiFieldSearch, EuiFlexGrid, EuiFormRow, EuiComboBox, - EuiKeyPadMenuItem, EuiFieldNumber, EuiSelect, EuiIconTip, @@ -25,11 +25,16 @@ import { EuiHorizontalRule, EuiLoadingSpinner, EuiEmptyPrompt, + EuiListGroupItem, + EuiListGroup, EuiLink, EuiText, + EuiNotificationBadge, } from '@elastic/eui'; import { some, filter, map, fold } from 'fp-ts/lib/Option'; import { pipe } from 'fp-ts/lib/pipeable'; +import { capitalize } from 'lodash'; +import { KibanaFeature } from '../../../../../features/public'; import { getDurationNumberInItsUnit, getDurationUnitValue, @@ -37,12 +42,23 @@ import { import { loadAlertTypes } from '../../lib/alert_api'; import { actionVariablesFromAlertType } from '../../lib/action_variables'; import { AlertReducerAction } from './alert_reducer'; -import { AlertTypeModel, Alert, IErrorObject, AlertAction, AlertTypeIndex } from '../../../types'; +import { + AlertTypeModel, + Alert, + IErrorObject, + AlertAction, + AlertTypeIndex, + AlertType, +} from '../../../types'; import { getTimeOptions } from '../../../common/lib/get_time_options'; import { useAlertsContext } from '../../context/alerts_context'; import { ActionForm } from '../action_connector_form'; import { ALERTS_FEATURE_ID } from '../../../../../alerts/common'; import { hasAllPrivilege, hasShowActionsCapability } from '../../lib/capabilities'; +import { SolutionFilter } from './solution_filter'; +import './alert_form.scss'; + +const ENTER_KEY = 13; export function validateBaseProperties(alertObject: Alert) { const validationResult = { errors: {} }; @@ -77,6 +93,10 @@ export function validateBaseProperties(alertObject: Alert) { return validationResult; } +function getProducerFeatureName(producer: string, kibanaFeatures: KibanaFeature[]) { + return kibanaFeatures.find((featureItem) => featureItem.id === producer)?.name; +} + interface AlertFormProps { alert: Alert; dispatch: React.Dispatch; @@ -104,12 +124,12 @@ export const AlertForm = ({ actionTypeRegistry, docLinks, capabilities, + kibanaFeatures, } = alertsContext; const canShowActions = hasShowActionsCapability(capabilities); const [alertTypeModel, setAlertTypeModel] = useState(null); - const [alertTypesIndex, setAlertTypesIndex] = useState(undefined); const [alertInterval, setAlertInterval] = useState( alert.schedule.interval ? getDurationNumberInItsUnit(alert.schedule.interval) : undefined ); @@ -123,20 +143,53 @@ export const AlertForm = ({ alert.throttle ? getDurationUnitValue(alert.throttle) : 'm' ); const [defaultActionGroupId, setDefaultActionGroupId] = useState(undefined); + const [alertTypesIndex, setAlertTypesIndex] = useState(null); + + const [availableAlertTypes, setAvailableAlertTypes] = useState< + Array<{ alertTypeModel: AlertTypeModel; alertType: AlertType }> + >([]); + const [filteredAlertTypes, setFilteredAlertTypes] = useState< + Array<{ alertTypeModel: AlertTypeModel; alertType: AlertType }> + >([]); + const [searchText, setSearchText] = useState(); + const [inputText, setInputText] = useState(); + const [solutions, setSolutions] = useState | undefined>(undefined); + const [solutionsFilter, setSolutionFilter] = useState([]); // load alert types useEffect(() => { (async () => { try { - const alertTypes = await loadAlertTypes({ http }); + const alertTypesResult = await loadAlertTypes({ http }); const index: AlertTypeIndex = new Map(); - for (const alertTypeItem of alertTypes) { + for (const alertTypeItem of alertTypesResult) { index.set(alertTypeItem.id, alertTypeItem); } if (alert.alertTypeId && index.has(alert.alertTypeId)) { setDefaultActionGroupId(index.get(alert.alertTypeId)!.defaultActionGroupId); } setAlertTypesIndex(index); + const availableAlertTypesResult = getAvailableAlertTypes(alertTypesResult); + setAvailableAlertTypes(availableAlertTypesResult); + + const solutionsResult = availableAlertTypesResult.reduce( + (result: Map, alertTypeItem) => { + if (!result.has(alertTypeItem.alertType.producer)) { + result.set( + alertTypeItem.alertType.producer, + (kibanaFeatures + ? getProducerFeatureName(alertTypeItem.alertType.producer, kibanaFeatures) + : capitalize(alertTypeItem.alertType.producer)) ?? + capitalize(alertTypeItem.alertType.producer) + ); + } + return result; + }, + new Map() + ); + setSolutions( + new Map([...solutionsResult.entries()].sort(([, a], [, b]) => a.localeCompare(b))) + ); } catch (e) { toastNotifications.addDanger({ title: i18n.translate( @@ -153,9 +206,17 @@ export const AlertForm = ({ setAlertTypeModel(alert.alertTypeId ? alertTypeRegistry.get(alert.alertTypeId) : null); }, [alert, alertTypeRegistry]); - const setAlertProperty = (key: string, value: any) => { - dispatch({ command: { type: 'setProperty' }, payload: { key, value } }); - }; + const setAlertProperty = useCallback( + (key: string, value: any) => { + dispatch({ command: { type: 'setProperty' }, payload: { key, value } }); + }, + [dispatch] + ); + + const setActions = useCallback( + (updatedActions: AlertAction[]) => setAlertProperty('actions', updatedActions), + [setAlertProperty] + ); const setAlertParams = (key: string, value: any) => { dispatch({ command: { type: 'setAlertParams' }, payload: { key, value } }); @@ -169,9 +230,61 @@ export const AlertForm = ({ dispatch({ command: { type: 'setAlertActionProperty' }, payload: { key, value, index } }); }; - const setActionParamsProperty = (key: string, value: any, index: number) => { - dispatch({ command: { type: 'setAlertActionParams' }, payload: { key, value, index } }); - }; + const setActionParamsProperty = useCallback( + (key: string, value: any, index: number) => { + dispatch({ command: { type: 'setAlertActionParams' }, payload: { key, value, index } }); + }, + [dispatch] + ); + + useEffect(() => { + const searchValue = searchText ? searchText.trim().toLocaleLowerCase() : null; + setFilteredAlertTypes( + availableAlertTypes + .filter((alertTypeItem) => + solutionsFilter.length > 0 + ? solutionsFilter.find((item) => alertTypeItem.alertType!.producer === item) + : alertTypeItem + ) + .filter((alertTypeItem) => + searchValue + ? alertTypeItem.alertTypeModel.name + .toString() + .toLocaleLowerCase() + .includes(searchValue) || + alertTypeItem.alertType!.producer.toLocaleLowerCase().includes(searchValue) || + alertTypeItem.alertTypeModel.description.toLocaleLowerCase().includes(searchValue) + : alertTypeItem + ) + ); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [alertTypeRegistry, availableAlertTypes, searchText, JSON.stringify(solutionsFilter)]); + + const getAvailableAlertTypes = (alertTypesResult: AlertType[]) => + alertTypeRegistry + .list() + .reduce( + ( + arr: Array<{ alertType: AlertType; alertTypeModel: AlertTypeModel }>, + alertTypeRegistryItem: AlertTypeModel + ) => { + const alertType = alertTypesResult.find((item) => alertTypeRegistryItem.id === item.id); + if (alertType) { + arr.push({ + alertType, + alertTypeModel: alertTypeRegistryItem, + }); + } + return arr; + }, + [] + ) + .filter((item) => item.alertType && hasAllPrivilege(alert, item.alertType)) + .filter((item) => + alert.consumer === ALERTS_FEATURE_ID + ? !item.alertTypeModel.requiresAppContext + : item.alertType!.producer === alert.consumer + ); const tagsOptions = alert.tags ? alert.tags.map((label: string) => ({ label })) : []; @@ -179,40 +292,88 @@ export const AlertForm = ({ ? alertTypeModel.alertParamsExpression : null; - const alertTypeRegistryList = alertTypesIndex - ? alertTypeRegistry - .list() - .filter( - (alertTypeRegistryItem: AlertTypeModel) => - alertTypesIndex.has(alertTypeRegistryItem.id) && - hasAllPrivilege(alert, alertTypesIndex.get(alertTypeRegistryItem.id)) - ) - .filter((alertTypeRegistryItem: AlertTypeModel) => - alert.consumer === ALERTS_FEATURE_ID - ? !alertTypeRegistryItem.requiresAppContext - : alertTypesIndex.get(alertTypeRegistryItem.id)!.producer === alert.consumer - ) - : []; + const alertTypesByProducer = filteredAlertTypes.reduce( + ( + result: Record>, + alertTypeValue + ) => { + const producer = alertTypeValue.alertType.producer; + if (producer) { + (result[producer] = result[producer] || []).push({ + name: + typeof alertTypeValue.alertTypeModel.name === 'string' + ? alertTypeValue.alertTypeModel.name + : alertTypeValue.alertTypeModel.name.props.defaultMessage, + id: alertTypeValue.alertTypeModel.id, + alertTypeItem: alertTypeValue.alertTypeModel, + }); + } + return result; + }, + {} + ); - const alertTypeNodes = alertTypeRegistryList.map(function (item, index) { - return ( - { - setAlertProperty('alertTypeId', item.id); - setAlertTypeModel(item); - setAlertProperty('params', {}); - if (alertTypesIndex && alertTypesIndex.has(item.id)) { - setDefaultActionGroupId(alertTypesIndex.get(item.id)!.defaultActionGroupId); - } - }} - > - - - ); - }); + const alertTypeNodes = Object.entries(alertTypesByProducer) + .sort(([a], [b]) => + solutions ? solutions.get(a)!.localeCompare(solutions.get(b)!) : a.localeCompare(b) + ) + .map(([solution, items], groupIndex) => ( + + + + + + {(kibanaFeatures + ? getProducerFeatureName(solution, kibanaFeatures) + : capitalize(solution)) ?? capitalize(solution)} + + + + + {items.length} + + + + + {items + .sort((a, b) => a.name.toString().localeCompare(b.name.toString())) + .map((item, index) => ( + + + {item.name} + +

{item.alertTypeItem.description}

+
+ + } + onClick={() => { + setAlertProperty('alertTypeId', item.id); + setActions([]); + setAlertTypeModel(item.alertTypeItem); + setAlertProperty('params', {}); + if (alertTypesIndex && alertTypesIndex.has(item.id)) { + setDefaultActionGroupId(alertTypesIndex.get(item.id)!.defaultActionGroupId); + } + }} + /> +
+ ))} +
+ +
+ )); const alertTypeDetails = ( @@ -289,26 +450,25 @@ export const AlertForm = ({ /> ) : null} - {canShowActions && defaultActionGroupId ? ( + {canShowActions && + defaultActionGroupId && + alertTypeModel && + alertTypesIndex?.has(alert.alertTypeId) ? ( - a.name.toUpperCase().localeCompare(b.name.toUpperCase()) - ) - : undefined - } + messageVariables={actionVariablesFromAlertType( + alertTypesIndex.get(alert.alertTypeId)! + ).sort((a, b) => a.name.toUpperCase().localeCompare(b.name.toUpperCase()))} defaultActionGroupId={defaultActionGroupId} + actionGroups={alertTypesIndex.get(alert.alertTypeId)!.actionGroups} setActionIdByIndex={(id: string, index: number) => setActionProperty('id', id, index)} - setAlertProperty={(updatedActions: AlertAction[]) => - setAlertProperty('actions', updatedActions) - } - setActionParamsProperty={(key: string, value: any, index: number) => - setActionParamsProperty(key, value, index) + setActionGroupIdByIndex={(group: string, index: number) => + setActionProperty('group', group, index) } + setAlertProperty={setActions} + setActionParamsProperty={setActionParamsProperty} http={http} actionTypeRegistry={actionTypeRegistry} defaultActionMessage={alertTypeModel?.defaultActionMessage} @@ -390,12 +550,9 @@ export const AlertForm = ({ {alertTypeModel ? ( {alertTypeDetails} - ) : alertTypeNodes.length ? ( + ) : availableAlertTypes.length ? ( - -
- -
-
+ +
+ +
+ + } + > + + + setInputText(e.target.value)} + onKeyUp={(e) => { + if (e.keyCode === ENTER_KEY) { + setSearchText(inputText); + } + }} + placeholder={i18n.translate( + 'xpack.triggersActionsUI.sections.alertForm.searchPlaceholderTitle', + { defaultMessage: 'Search' } + )} + /> + + {solutions ? ( + + setSolutionFilter(selectedSolutions)} + /> + + ) : null} + +
- - {alertTypeNodes} - + {alertTypeNodes}
) : alertTypesIndex ? ( diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/solution_filter.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/solution_filter.tsx new file mode 100644 index 0000000000000..7caee22cf7633 --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/solution_filter.tsx @@ -0,0 +1,73 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { useEffect, useState } from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiFilterGroup, EuiPopover, EuiFilterButton, EuiFilterSelectItem } from '@elastic/eui'; + +interface SolutionFilterProps { + solutions: Map; + onChange?: (selectedSolutions: string[]) => void; +} + +export const SolutionFilter: React.FunctionComponent = ({ + solutions, + onChange, +}: SolutionFilterProps) => { + const [selectedValues, setSelectedValues] = useState([]); + const [isPopoverOpen, setIsPopoverOpen] = useState(false); + + useEffect(() => { + if (onChange) { + onChange(selectedValues); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [selectedValues]); + + return ( + + setIsPopoverOpen(false)} + button={ + 0} + numActiveFilters={selectedValues.length} + numFilters={selectedValues.length} + onClick={() => setIsPopoverOpen(!isPopoverOpen)} + data-test-subj="solutionsFilterButton" + > + + + } + > +
+ {[...solutions.entries()].map(([id, title]) => ( + { + const isPreviouslyChecked = selectedValues.includes(id); + if (isPreviouslyChecked) { + setSelectedValues(selectedValues.filter((val) => val !== id)); + } else { + setSelectedValues([...selectedValues, id]); + } + }} + checked={selectedValues.includes(id) ? 'on' : undefined} + data-test-subj={`solution${id}FilterOption`} + > + {title} + + ))} +
+
+
+ ); +}; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_list/components/alerts_list.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_list/components/alerts_list.tsx index 3b0cd0b177b1b..75f359888a858 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_list/components/alerts_list.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_list/components/alerts_list.tsx @@ -672,6 +672,7 @@ export const AlertsList: React.FunctionComponent = () => { capabilities, dataUi: dataPlugin.ui, dataIndexPatterns: dataPlugin.indexPatterns, + kibanaFeatures, }} > { + expect(DefaultActionMessage).to.be.ok(); + }); + // The tests below create two alerts, one that will fire, one that will // never fire; the tests ensure the ones that should fire, do fire, and // those that shouldn't fire, do not fire. @@ -85,7 +92,7 @@ export default function alertTests({ getService }: FtrProviderContext) { const docs = await waitForDocs(2); for (const doc of docs) { const { group } = doc._source; - const { name, value, title, message } = doc._source.params; + const { name, title, message } = doc._source.params; expect(name).to.be('always fire'); expect(group).to.be('all documents'); @@ -93,9 +100,8 @@ export default function alertTests({ getService }: FtrProviderContext) { // we'll check title and message in this test, but not subsequent ones expect(title).to.be('alert always fire group all documents exceeded threshold'); - const expectedPrefix = `alert always fire group all documents value ${value} exceeded threshold count > -1 over`; - const messagePrefix = message.substr(0, expectedPrefix.length); - expect(messagePrefix).to.be(expectedPrefix); + const messagePattern = /alert always fire group all documents value \d+ exceeded threshold count > -1 over 15s on \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/; + expect(message).to.match(messagePattern); } }); @@ -128,10 +134,13 @@ export default function alertTests({ getService }: FtrProviderContext) { for (const doc of docs) { const { group } = doc._source; - const { name } = doc._source.params; + const { name, message } = doc._source.params; expect(name).to.be('always fire'); if (group === 'group-0') inGroup0++; + + const messagePattern = /alert always fire group group-\d value \d+ exceeded threshold count .+ over 15s on \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/; + expect(message).to.match(messagePattern); } // there should be 2 docs in group-0, rando split between others @@ -163,9 +172,12 @@ export default function alertTests({ getService }: FtrProviderContext) { const docs = await waitForDocs(2); for (const doc of docs) { - const { name } = doc._source.params; + const { name, message } = doc._source.params; expect(name).to.be('always fire'); + + const messagePattern = /alert always fire group all documents value \d+ exceeded threshold sum\(testedValue\) between 0,1000000 over 15s on \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/; + expect(message).to.match(messagePattern); } }); @@ -195,9 +207,12 @@ export default function alertTests({ getService }: FtrProviderContext) { const docs = await waitForDocs(4); for (const doc of docs) { - const { name } = doc._source.params; + const { name, message } = doc._source.params; expect(name).to.be('always fire'); + + const messagePattern = /alert always fire group all documents value .+ exceeded threshold avg\(testedValue\) .+ 0 over 15s on \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/; + expect(message).to.match(messagePattern); } }); @@ -232,10 +247,13 @@ export default function alertTests({ getService }: FtrProviderContext) { for (const doc of docs) { const { group } = doc._source; - const { name } = doc._source.params; + const { name, message } = doc._source.params; expect(name).to.be('always fire'); if (group === 'group-2') inGroup2++; + + const messagePattern = /alert always fire group group-. value \d+ exceeded threshold max\(testedValue\) .* 0 over 15s on \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/; + expect(message).to.match(messagePattern); } // there should be 2 docs in group-2, rando split between others @@ -274,10 +292,13 @@ export default function alertTests({ getService }: FtrProviderContext) { for (const doc of docs) { const { group } = doc._source; - const { name } = doc._source.params; + const { name, message } = doc._source.params; expect(name).to.be('always fire'); if (group === 'group-0') inGroup0++; + + const messagePattern = /alert always fire group group-. value \d+ exceeded threshold min\(testedValue\) .* 0 over 15s on \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/; + expect(message).to.match(messagePattern); } // there should be 2 docs in group-0, rando split between others @@ -329,7 +350,7 @@ export default function alertTests({ getService }: FtrProviderContext) { name: '{{{alertName}}}', value: '{{{context.value}}}', title: '{{{context.title}}}', - message: '{{{context.message}}}', + message: DefaultActionMessage, }, date: '{{{context.date}}}', // TODO: I wanted to write the alert value here, but how? diff --git a/x-pack/test/api_integration/apis/kibana/stats/stats.js b/x-pack/test/api_integration/apis/kibana/stats/stats.js index f0a41f1f008ba..ae4ddad66863b 100644 --- a/x-pack/test/api_integration/apis/kibana/stats/stats.js +++ b/x-pack/test/api_integration/apis/kibana/stats/stats.js @@ -30,7 +30,7 @@ export default function ({ getService }) { }); it('should return 401 for extended', async () => { - await supertestNoAuth.get('/api/stats?extended').expect(401); + await supertestNoAuth.get('/api/stats?extended').auth(null, null).expect(401); }); }); diff --git a/x-pack/test/api_integration/apis/management/rollup/constants.js b/x-pack/test/api_integration/apis/management/rollup/constants.js index fe899c4c10c88..0313434cf716c 100644 --- a/x-pack/test/api_integration/apis/management/rollup/constants.js +++ b/x-pack/test/api_integration/apis/management/rollup/constants.js @@ -5,7 +5,7 @@ */ export const API_BASE_PATH = '/api/rollup'; -export const INDEX_PATTERNS_EXTENSION_BASE_PATH = '/api/index_patterns/rollup'; +export const INDEX_PATTERNS_EXTENSION_BASE_PATH = '/api/index_patterns'; export const ROLLUP_INDEX_NAME = 'rollup_index'; export const INDEX_TO_ROLLUP_MAPPINGS = { properties: { diff --git a/x-pack/test/api_integration/apis/management/rollup/index_patterns_extensions.js b/x-pack/test/api_integration/apis/management/rollup/index_patterns_extensions.js index 357b952e7e66d..0a93e8b8bd1e3 100644 --- a/x-pack/test/api_integration/apis/management/rollup/index_patterns_extensions.js +++ b/x-pack/test/api_integration/apis/management/rollup/index_patterns_extensions.js @@ -26,7 +26,6 @@ export default function ({ getService }) { describe('query params validation', () => { let uri; let body; - let params; it('"pattern" is required', async () => { uri = `${BASE_URI}`; @@ -36,62 +35,17 @@ export default function ({ getService }) { ); }); - it('"params" is required', async () => { - params = { pattern: 'foo' }; - uri = `${BASE_URI}?${stringify(params, { sort: false })}`; - ({ body } = await supertest.get(uri).expect(400)); - expect(body.message).to.contain( - '[request query.params]: expected value of type [string]' - ); - }); - - it('"params" must be a valid JSON string', async () => { - params = { pattern: 'foo', params: 'foobarbaz' }; - uri = `${BASE_URI}?${stringify(params, { sort: false })}`; - ({ body } = await supertest.get(uri).expect(400)); - expect(body.message).to.contain('[request query.params]: expected JSON string'); - }); - - it('"params" requires a "rollup_index" property', async () => { - params = { pattern: 'foo', params: JSON.stringify({}) }; - uri = `${BASE_URI}?${stringify(params, { sort: false })}`; - ({ body } = await supertest.get(uri).expect(400)); - expect(body.message).to.contain('[request query.params]: "rollup_index" is required'); - }); - - it('"params" only accepts a "rollup_index" property', async () => { - params = { - pattern: 'foo', - params: JSON.stringify({ rollup_index: 'my_index', someProp: 'bar' }), - }; - uri = `${BASE_URI}?${stringify(params, { sort: false })}`; - ({ body } = await supertest.get(uri).expect(400)); - expect(body.message).to.contain('[request query.params]: someProp is not allowed'); - }); - - it('"meta_fields" must be an Array', async () => { - params = { - pattern: 'foo', - params: JSON.stringify({ rollup_index: 'bar' }), - meta_fields: 'stringValue', - }; - uri = `${BASE_URI}?${stringify(params, { sort: false })}`; - ({ body } = await supertest.get(uri).expect(400)); - expect(body.message).to.contain( - '[request query.meta_fields]: could not parse array value from json input' - ); - }); - it('should return 404 the rollup index to query does not exist', async () => { uri = `${BASE_URI}?${stringify( { pattern: 'foo', - params: JSON.stringify({ rollup_index: 'bar' }), + type: 'rollup', + rollup_index: 'bar', }, { sort: false } )}`; ({ body } = await supertest.get(uri).expect(404)); - expect(body.message).to.contain('[index_not_found_exception] no such index [bar]'); + expect(body.message).to.contain('No indices match pattern "foo"'); }); }); @@ -105,7 +59,8 @@ export default function ({ getService }) { // Query for wildcard const params = { pattern: indexName, - params: JSON.stringify({ rollup_index: rollupIndex }), + type: 'rollup', + rollup_index: rollupIndex, }; const uri = `${BASE_URI}?${stringify(params, { sort: false })}`; const { body } = await supertest.get(uri).expect(200); diff --git a/x-pack/test/common/services/ingest_manager.ts b/x-pack/test/common/services/ingest_manager.ts index 2fcfaa014b2e1..42c1d20437c7b 100644 --- a/x-pack/test/common/services/ingest_manager.ts +++ b/x-pack/test/common/services/ingest_manager.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import { FtrProviderContext } from '../ftr_provider_context'; -import { fleetSetupRouteService } from '../../../plugins/ingest_manager/common'; +import { fleetSetupRouteService } from '../../../plugins/fleet/common'; export function IngestManagerProvider({ getService }: FtrProviderContext) { const supertest = getService('supertest'); diff --git a/x-pack/test/functional/config.js b/x-pack/test/functional/config.js index 2072f4aa1c571..11e4111696ccf 100644 --- a/x-pack/test/functional/config.js +++ b/x-pack/test/functional/config.js @@ -88,6 +88,7 @@ export default async function ({ readConfigFile }) { '--xpack.security.encryptionKey="wuGNaIhoMpk5sO4UBxgr3NyW1sFcLgIf"', // server restarts should not invalidate active sessions '--xpack.encryptedSavedObjects.encryptionKey="DkdXazszSCYexXqz4YktBGHCRkV6hyNK"', '--timelion.ui.enabled=true', + '--savedObjects.maxImportPayloadBytes=10485760', // for OSS test management/_import_objects ], }, uiSettings: { diff --git a/x-pack/test/functional/es_archives/endpoint/resolver_tree/alert_events/data.json.gz b/x-pack/test/functional/es_archives/endpoint/resolver_tree/alert_events/data.json.gz new file mode 100644 index 0000000000000..997a7a5322a11 Binary files /dev/null and b/x-pack/test/functional/es_archives/endpoint/resolver_tree/alert_events/data.json.gz differ diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alert_create_flyout.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alert_create_flyout.ts index 7d99d3635106d..0f6da936f8644 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alert_create_flyout.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alert_create_flyout.ts @@ -55,6 +55,12 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await nameInput.click(); } + async function defineAlwaysFiringAlert(alertName: string) { + await pageObjects.triggersActionsUI.clickCreateAlertButton(); + await testSubjects.setValue('alertNameInput', alertName); + await testSubjects.click('test.always-firing-SelectOption'); + } + describe('create alert', function () { before(async () => { await pageObjects.common.navigateToApp('triggersActions'); @@ -73,10 +79,13 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await find.clickByCssSelector('[data-test-subj="saveActionButtonModal"]:not(disabled)'); const createdConnectorToastTitle = await pageObjects.common.closeToast(); expect(createdConnectorToastTitle).to.eql(`Created '${slackConnectorName}'`); + const messageTextArea = await find.byCssSelector('[data-test-subj="messageTextArea"]'); + expect(await messageTextArea.getAttribute('value')).to.eql( + 'alert {{alertName}} group {{context.group}} value {{context.value}} exceeded threshold {{context.function}} over {{params.timeWindowSize}}{{params.timeWindowUnit}} on {{context.date}}' + ); await testSubjects.setValue('messageTextArea', 'test message '); await testSubjects.click('messageAddVariableButton'); await testSubjects.click('variableMenuButton-0'); - const messageTextArea = await find.byCssSelector('[data-test-subj="messageTextArea"]'); expect(await messageTextArea.getAttribute('value')).to.eql('test message {{alertId}}'); await messageTextArea.type(' some additional text '); @@ -106,6 +115,57 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await deleteAlerts(alertsToDelete.map((alertItem: { id: string }) => alertItem.id)); }); + it('should create an alert with actions in multiple groups', async () => { + const alertName = generateUniqueKey(); + await defineAlwaysFiringAlert(alertName); + + // create Slack connector and attach an action using it + await testSubjects.click('.slack-ActionTypeSelectOption'); + await testSubjects.click('addNewActionConnectorButton-.slack'); + const slackConnectorName = generateUniqueKey(); + await testSubjects.setValue('nameInput', slackConnectorName); + await testSubjects.setValue('slackWebhookUrlInput', 'https://test'); + await find.clickByCssSelector('[data-test-subj="saveActionButtonModal"]:not(disabled)'); + const createdConnectorToastTitle = await pageObjects.common.closeToast(); + expect(createdConnectorToastTitle).to.eql(`Created '${slackConnectorName}'`); + await testSubjects.setValue('messageTextArea', 'test message '); + await ( + await find.byCssSelector( + '[data-test-subj="alertActionAccordion-0"] [data-test-subj="messageTextArea"]' + ) + ).type('some text '); + + await testSubjects.click('addAlertActionButton'); + await testSubjects.click('.slack-ActionTypeSelectOption'); + await testSubjects.setValue('messageTextArea', 'test message '); + await ( + await find.byCssSelector( + '[data-test-subj="alertActionAccordion-1"] [data-test-subj="messageTextArea"]' + ) + ).type('some text '); + + await testSubjects.click('addNewActionConnectorActionGroup-1'); + await testSubjects.click('addNewActionConnectorActionGroup-1-option-other'); + + await testSubjects.click('saveAlertButton'); + const toastTitle = await pageObjects.common.closeToast(); + expect(toastTitle).to.eql(`Created alert "${alertName}"`); + await pageObjects.triggersActionsUI.searchAlerts(alertName); + const searchResultsAfterSave = await pageObjects.triggersActionsUI.getAlertsList(); + expect(searchResultsAfterSave).to.eql([ + { + name: alertName, + tagsText: '', + alertType: 'Always Firing', + interval: '1m', + }, + ]); + + // clean up created alert + const alertsToDelete = await getAlertsByName(alertName); + await deleteAlerts(alertsToDelete.map((alertItem: { id: string }) => alertItem.id)); + }); + it('should show save confirmation before creating alert with no actions', async () => { const alertName = generateUniqueKey(); await defineAlert(alertName); diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/details.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/details.ts index 9e4006681dc8d..1d86d95b7a796 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/details.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/details.ts @@ -306,7 +306,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); }); - describe('Alert Instances', function () { + // FLAKY: https://github.com/elastic/kibana/issues/57426 + describe.skip('Alert Instances', function () { const testRunUuid = uuid.v4(); let alert: any; diff --git a/x-pack/test/functional_with_es_ssl/fixtures/plugins/alerts/server/plugin.ts b/x-pack/test/functional_with_es_ssl/fixtures/plugins/alerts/server/plugin.ts index e3927f6bfffb9..6f9d010378624 100644 --- a/x-pack/test/functional_with_es_ssl/fixtures/plugins/alerts/server/plugin.ts +++ b/x-pack/test/functional_with_es_ssl/fixtures/plugins/alerts/server/plugin.ts @@ -78,6 +78,7 @@ function createAlwaysFiringAlertType(alerts: AlertingSetup) { { id: 'default', name: 'Default' }, { id: 'other', name: 'Other' }, ], + defaultActionGroupId: 'default', producer: 'alerts', async executor(alertExecutorOptions: any) { const { services, state, params } = alertExecutorOptions; diff --git a/x-pack/test/ingest_manager_api_integration/apis/epm/bulk_upgrade.ts b/x-pack/test/ingest_manager_api_integration/apis/epm/bulk_upgrade.ts index 7c07fd47a66af..3f32d445e1fe7 100644 --- a/x-pack/test/ingest_manager_api_integration/apis/epm/bulk_upgrade.ts +++ b/x-pack/test/ingest_manager_api_integration/apis/epm/bulk_upgrade.ts @@ -11,7 +11,7 @@ import { BulkInstallPackageInfo, BulkInstallPackagesResponse, IBulkInstallPackageHTTPError, -} from '../../../../plugins/ingest_manager/common'; +} from '../../../../plugins/fleet/common'; export default function (providerContext: FtrProviderContext) { const { getService } = providerContext; diff --git a/x-pack/test/ingest_manager_api_integration/apis/epm/install_remove_assets.ts b/x-pack/test/ingest_manager_api_integration/apis/epm/install_remove_assets.ts index 8e8e4f010bcb5..2ae4273bfa7e8 100644 --- a/x-pack/test/ingest_manager_api_integration/apis/epm/install_remove_assets.ts +++ b/x-pack/test/ingest_manager_api_integration/apis/epm/install_remove_assets.ts @@ -6,7 +6,7 @@ import expect from '@kbn/expect'; import { sortBy } from 'lodash'; -import { AssetReference } from '../../../../plugins/ingest_manager/common'; +import { AssetReference } from '../../../../plugins/fleet/common'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry } from '../../helpers'; diff --git a/x-pack/test/ingest_manager_api_integration/apis/epm/install_update.ts b/x-pack/test/ingest_manager_api_integration/apis/epm/install_update.ts index af64d83a8a139..429d70836a6c1 100644 --- a/x-pack/test/ingest_manager_api_integration/apis/epm/install_update.ts +++ b/x-pack/test/ingest_manager_api_integration/apis/epm/install_update.ts @@ -10,7 +10,7 @@ import { skipIfNoDockerRegistry } from '../../helpers'; import { PACKAGES_SAVED_OBJECT_TYPE, MAX_TIME_COMPLETE_INSTALL, -} from '../../../../plugins/ingest_manager/common'; +} from '../../../../plugins/fleet/common'; export default function (providerContext: FtrProviderContext) { const { getService } = providerContext; diff --git a/x-pack/test/ingest_manager_api_integration/apis/epm/package_install_complete.ts b/x-pack/test/ingest_manager_api_integration/apis/epm/package_install_complete.ts index 2e7ab199a7fbc..edd6cd4e107a5 100644 --- a/x-pack/test/ingest_manager_api_integration/apis/epm/package_install_complete.ts +++ b/x-pack/test/ingest_manager_api_integration/apis/epm/package_install_complete.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; import { PACKAGES_SAVED_OBJECT_TYPE, MAX_TIME_COMPLETE_INSTALL, -} from '../../../../plugins/ingest_manager/common'; +} from '../../../../plugins/fleet/common'; import { skipIfNoDockerRegistry } from '../../helpers'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; diff --git a/x-pack/test/ingest_manager_api_integration/apis/epm/setup.ts b/x-pack/test/ingest_manager_api_integration/apis/epm/setup.ts index 15cff79475f08..3bab7411bed88 100644 --- a/x-pack/test/ingest_manager_api_integration/apis/epm/setup.ts +++ b/x-pack/test/ingest_manager_api_integration/apis/epm/setup.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry } from '../../helpers'; -import { GetInfoResponse, Installed } from '../../../../plugins/ingest_manager/common'; +import { GetInfoResponse, Installed } from '../../../../plugins/fleet/common'; export default function (providerContext: FtrProviderContext) { const { getService } = providerContext; diff --git a/x-pack/test/ingest_manager_api_integration/apis/epm/template.ts b/x-pack/test/ingest_manager_api_integration/apis/epm/template.ts index c92dac3334de3..1fc3eac026b65 100644 --- a/x-pack/test/ingest_manager_api_integration/apis/epm/template.ts +++ b/x-pack/test/ingest_manager_api_integration/apis/epm/template.ts @@ -6,7 +6,7 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; -import { getTemplate } from '../../../../plugins/ingest_manager/server/services/epm/elasticsearch/template/template'; +import { getTemplate } from '../../../../plugins/fleet/server/services/epm/elasticsearch/template/template'; export default function ({ getService }: FtrProviderContext) { const indexPattern = 'foo'; diff --git a/x-pack/test/ingest_manager_api_integration/apis/fleet/agents/upgrade.ts b/x-pack/test/ingest_manager_api_integration/apis/fleet/agents/upgrade.ts index 12d7780ad50d4..cbb07b91caf34 100644 --- a/x-pack/test/ingest_manager_api_integration/apis/fleet/agents/upgrade.ts +++ b/x-pack/test/ingest_manager_api_integration/apis/fleet/agents/upgrade.ts @@ -9,7 +9,7 @@ import semver from 'semver'; import { FtrProviderContext } from '../../../../api_integration/ftr_provider_context'; import { setupIngest } from './services'; import { skipIfNoDockerRegistry } from '../../../helpers'; -import { AGENT_SAVED_OBJECT_TYPE } from '../../../../../plugins/ingest_manager/common'; +import { AGENT_SAVED_OBJECT_TYPE } from '../../../../../plugins/fleet/common'; const makeSnapshotVersion = (version: string) => { return version.endsWith('-SNAPSHOT') ? version : `${version}-SNAPSHOT`; diff --git a/x-pack/test/kerberos_api_integration/apis/index.ts b/x-pack/test/kerberos_api_integration/apis/index.ts deleted file mode 100644 index 17da3ea7acc8d..0000000000000 --- a/x-pack/test/kerberos_api_integration/apis/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { FtrProviderContext } from '../ftr_provider_context'; - -export default function ({ loadTestFile }: FtrProviderContext) { - describe('apis Kerberos', function () { - this.tags('ciGroup6'); - loadTestFile(require.resolve('./security')); - }); -} diff --git a/x-pack/test/kerberos_api_integration/services.ts b/x-pack/test/kerberos_api_integration/services.ts deleted file mode 100644 index dadae9c331a46..0000000000000 --- a/x-pack/test/kerberos_api_integration/services.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { services as commonServices } from '../common/services'; -import { services as apiIntegrationServices } from '../api_integration/services'; - -export const services = { - ...commonServices, - legacyEs: apiIntegrationServices.legacyEs, - esSupertest: apiIntegrationServices.esSupertest, - supertestWithoutAuth: apiIntegrationServices.supertestWithoutAuth, -}; diff --git a/x-pack/test/oidc_api_integration/ftr_provider_context.d.ts b/x-pack/test/oidc_api_integration/ftr_provider_context.d.ts deleted file mode 100644 index e3add3748f56d..0000000000000 --- a/x-pack/test/oidc_api_integration/ftr_provider_context.d.ts +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { GenericFtrProviderContext } from '@kbn/test/types/ftr'; - -import { services } from './services'; - -export type FtrProviderContext = GenericFtrProviderContext; diff --git a/x-pack/test/oidc_api_integration/services.ts b/x-pack/test/oidc_api_integration/services.ts deleted file mode 100644 index e2abfa71451bc..0000000000000 --- a/x-pack/test/oidc_api_integration/services.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { services as commonServices } from '../common/services'; -import { services as apiIntegrationServices } from '../api_integration/services'; - -export const services = { - ...commonServices, - legacyEs: apiIntegrationServices.legacyEs, - supertestWithoutAuth: apiIntegrationServices.supertestWithoutAuth, -}; diff --git a/x-pack/test/pki_api_integration/apis/index.ts b/x-pack/test/pki_api_integration/apis/index.ts deleted file mode 100644 index 01b537fc07d1b..0000000000000 --- a/x-pack/test/pki_api_integration/apis/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { FtrProviderContext } from '../ftr_provider_context'; - -export default function ({ loadTestFile }: FtrProviderContext) { - describe('apis PKI', function () { - this.tags('ciGroup6'); - loadTestFile(require.resolve('./security')); - }); -} diff --git a/x-pack/test/pki_api_integration/ftr_provider_context.d.ts b/x-pack/test/pki_api_integration/ftr_provider_context.d.ts deleted file mode 100644 index e3add3748f56d..0000000000000 --- a/x-pack/test/pki_api_integration/ftr_provider_context.d.ts +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { GenericFtrProviderContext } from '@kbn/test/types/ftr'; - -import { services } from './services'; - -export type FtrProviderContext = GenericFtrProviderContext; diff --git a/x-pack/test/pki_api_integration/services.ts b/x-pack/test/pki_api_integration/services.ts deleted file mode 100644 index 73ec6fe396392..0000000000000 --- a/x-pack/test/pki_api_integration/services.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { services as commonServices } from '../common/services'; -import { services as apiIntegrationServices } from '../api_integration/services'; - -export const services = { - ...commonServices, - esSupertest: apiIntegrationServices.esSupertest, - supertestWithoutAuth: apiIntegrationServices.supertestWithoutAuth, -}; diff --git a/x-pack/test/kerberos_api_integration/fixtures/README.md b/x-pack/test/security_api_integration/fixtures/kerberos/README.md similarity index 100% rename from x-pack/test/kerberos_api_integration/fixtures/README.md rename to x-pack/test/security_api_integration/fixtures/kerberos/README.md diff --git a/x-pack/test/kerberos_api_integration/fixtures/kerberos_tools.ts b/x-pack/test/security_api_integration/fixtures/kerberos/kerberos_tools.ts similarity index 100% rename from x-pack/test/kerberos_api_integration/fixtures/kerberos_tools.ts rename to x-pack/test/security_api_integration/fixtures/kerberos/kerberos_tools.ts diff --git a/x-pack/test/kerberos_api_integration/fixtures/krb5.conf b/x-pack/test/security_api_integration/fixtures/kerberos/krb5.conf similarity index 100% rename from x-pack/test/kerberos_api_integration/fixtures/krb5.conf rename to x-pack/test/security_api_integration/fixtures/kerberos/krb5.conf diff --git a/x-pack/test/kerberos_api_integration/fixtures/krb5.keytab b/x-pack/test/security_api_integration/fixtures/kerberos/krb5.keytab similarity index 100% rename from x-pack/test/kerberos_api_integration/fixtures/krb5.keytab rename to x-pack/test/security_api_integration/fixtures/kerberos/krb5.keytab diff --git a/x-pack/test/oidc_api_integration/fixtures/README.md b/x-pack/test/security_api_integration/fixtures/oidc/README.md similarity index 100% rename from x-pack/test/oidc_api_integration/fixtures/README.md rename to x-pack/test/security_api_integration/fixtures/oidc/README.md diff --git a/x-pack/test/oidc_api_integration/fixtures/jwks.json b/x-pack/test/security_api_integration/fixtures/oidc/jwks.json similarity index 100% rename from x-pack/test/oidc_api_integration/fixtures/jwks.json rename to x-pack/test/security_api_integration/fixtures/oidc/jwks.json diff --git a/x-pack/test/oidc_api_integration/fixtures/jwks_private.pem b/x-pack/test/security_api_integration/fixtures/oidc/jwks_private.pem similarity index 100% rename from x-pack/test/oidc_api_integration/fixtures/jwks_private.pem rename to x-pack/test/security_api_integration/fixtures/oidc/jwks_private.pem diff --git a/x-pack/test/oidc_api_integration/fixtures/jwks_public.pem b/x-pack/test/security_api_integration/fixtures/oidc/jwks_public.pem similarity index 100% rename from x-pack/test/oidc_api_integration/fixtures/jwks_public.pem rename to x-pack/test/security_api_integration/fixtures/oidc/jwks_public.pem diff --git a/x-pack/test/oidc_api_integration/fixtures/oidc_provider/kibana.json b/x-pack/test/security_api_integration/fixtures/oidc/oidc_provider/kibana.json similarity index 100% rename from x-pack/test/oidc_api_integration/fixtures/oidc_provider/kibana.json rename to x-pack/test/security_api_integration/fixtures/oidc/oidc_provider/kibana.json diff --git a/x-pack/test/oidc_api_integration/fixtures/oidc_provider/server/index.ts b/x-pack/test/security_api_integration/fixtures/oidc/oidc_provider/server/index.ts similarity index 85% rename from x-pack/test/oidc_api_integration/fixtures/oidc_provider/server/index.ts rename to x-pack/test/security_api_integration/fixtures/oidc/oidc_provider/server/index.ts index 58401e725830f..082fec55c3413 100644 --- a/x-pack/test/oidc_api_integration/fixtures/oidc_provider/server/index.ts +++ b/x-pack/test/security_api_integration/fixtures/oidc/oidc_provider/server/index.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { PluginInitializer } from '../../../../../../src/core/server'; +import type { PluginInitializer } from '../../../../../../../src/core/server'; import { initRoutes } from './init_routes'; export const plugin: PluginInitializer = () => ({ diff --git a/x-pack/test/oidc_api_integration/fixtures/oidc_provider/server/init_routes.ts b/x-pack/test/security_api_integration/fixtures/oidc/oidc_provider/server/init_routes.ts similarity index 98% rename from x-pack/test/oidc_api_integration/fixtures/oidc_provider/server/init_routes.ts rename to x-pack/test/security_api_integration/fixtures/oidc/oidc_provider/server/init_routes.ts index 73f92139806e3..8f75246d995c3 100644 --- a/x-pack/test/oidc_api_integration/fixtures/oidc_provider/server/init_routes.ts +++ b/x-pack/test/security_api_integration/fixtures/oidc/oidc_provider/server/init_routes.ts @@ -5,7 +5,7 @@ */ import { schema } from '@kbn/config-schema'; -import { IRouter } from '../../../../../../src/core/server'; +import type { IRouter } from '../../../../../../../src/core/server'; import { createTokens } from '../../oidc_tools'; export function initRoutes(router: IRouter) { diff --git a/x-pack/test/oidc_api_integration/fixtures/oidc_tools.ts b/x-pack/test/security_api_integration/fixtures/oidc/oidc_tools.ts similarity index 100% rename from x-pack/test/oidc_api_integration/fixtures/oidc_tools.ts rename to x-pack/test/security_api_integration/fixtures/oidc/oidc_tools.ts diff --git a/x-pack/test/pki_api_integration/fixtures/README.md b/x-pack/test/security_api_integration/fixtures/pki/README.md similarity index 100% rename from x-pack/test/pki_api_integration/fixtures/README.md rename to x-pack/test/security_api_integration/fixtures/pki/README.md diff --git a/x-pack/test/pki_api_integration/fixtures/first_client.p12 b/x-pack/test/security_api_integration/fixtures/pki/first_client.p12 similarity index 100% rename from x-pack/test/pki_api_integration/fixtures/first_client.p12 rename to x-pack/test/security_api_integration/fixtures/pki/first_client.p12 diff --git a/x-pack/test/pki_api_integration/fixtures/kibana_ca.crt b/x-pack/test/security_api_integration/fixtures/pki/kibana_ca.crt similarity index 100% rename from x-pack/test/pki_api_integration/fixtures/kibana_ca.crt rename to x-pack/test/security_api_integration/fixtures/pki/kibana_ca.crt diff --git a/x-pack/test/pki_api_integration/fixtures/kibana_ca.key b/x-pack/test/security_api_integration/fixtures/pki/kibana_ca.key similarity index 100% rename from x-pack/test/pki_api_integration/fixtures/kibana_ca.key rename to x-pack/test/security_api_integration/fixtures/pki/kibana_ca.key diff --git a/x-pack/test/pki_api_integration/fixtures/second_client.p12 b/x-pack/test/security_api_integration/fixtures/pki/second_client.p12 similarity index 100% rename from x-pack/test/pki_api_integration/fixtures/second_client.p12 rename to x-pack/test/security_api_integration/fixtures/pki/second_client.p12 diff --git a/x-pack/test/pki_api_integration/fixtures/untrusted_client.p12 b/x-pack/test/security_api_integration/fixtures/pki/untrusted_client.p12 similarity index 100% rename from x-pack/test/pki_api_integration/fixtures/untrusted_client.p12 rename to x-pack/test/security_api_integration/fixtures/pki/untrusted_client.p12 diff --git a/x-pack/test/kerberos_api_integration/config.ts b/x-pack/test/security_api_integration/kerberos.config.ts similarity index 82% rename from x-pack/test/kerberos_api_integration/config.ts rename to x-pack/test/security_api_integration/kerberos.config.ts index 7b65d79e18e7d..08c2007989083 100644 --- a/x-pack/test/kerberos_api_integration/config.ts +++ b/x-pack/test/security_api_integration/kerberos.config.ts @@ -11,21 +11,15 @@ import { services } from './services'; export default async function ({ readConfigFile }: FtrConfigProviderContext) { const xPackAPITestsConfig = await readConfigFile(require.resolve('../api_integration/config.ts')); - const kerberosKeytabPath = resolve( - __dirname, - '../../test/kerberos_api_integration/fixtures/krb5.keytab' - ); - const kerberosConfigPath = resolve( - __dirname, - '../../test/kerberos_api_integration/fixtures/krb5.conf' - ); + const kerberosKeytabPath = resolve(__dirname, './fixtures/kerberos/krb5.keytab'); + const kerberosConfigPath = resolve(__dirname, './fixtures/kerberos/krb5.conf'); return { - testFiles: [require.resolve('./apis')], + testFiles: [require.resolve('./tests/kerberos')], servers: xPackAPITestsConfig.get('servers'), services, junit: { - reportName: 'X-Pack Kerberos API Integration Tests', + reportName: 'X-Pack Security API Integration Tests (Kerberos)', }, esTestCluster: { diff --git a/x-pack/test/kerberos_api_integration/anonymous_access.config.ts b/x-pack/test/security_api_integration/kerberos_anonymous_access.config.ts similarity index 87% rename from x-pack/test/kerberos_api_integration/anonymous_access.config.ts rename to x-pack/test/security_api_integration/kerberos_anonymous_access.config.ts index 17362831a6cd0..6621b536c7ca9 100644 --- a/x-pack/test/kerberos_api_integration/anonymous_access.config.ts +++ b/x-pack/test/security_api_integration/kerberos_anonymous_access.config.ts @@ -7,13 +7,13 @@ import { FtrConfigProviderContext } from '@kbn/test/types/ftr'; export default async function ({ readConfigFile }: FtrConfigProviderContext) { - const kerberosAPITestsConfig = await readConfigFile(require.resolve('./config.ts')); + const kerberosAPITestsConfig = await readConfigFile(require.resolve('./kerberos.config.ts')); return { ...kerberosAPITestsConfig.getAll(), junit: { - reportName: 'X-Pack Kerberos API with Anonymous Access Integration Tests', + reportName: 'X-Pack Security API Integration Tests (Kerberos with Anonymous Access)', }, esTestCluster: { diff --git a/x-pack/test/security_api_integration/login_selector.config.ts b/x-pack/test/security_api_integration/login_selector.config.ts index 0e43715ba808e..9688d42cb4361 100644 --- a/x-pack/test/security_api_integration/login_selector.config.ts +++ b/x-pack/test/security_api_integration/login_selector.config.ts @@ -15,13 +15,13 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { const xPackAPITestsConfig = await readConfigFile(require.resolve('../api_integration/config.ts')); const kibanaPort = xPackAPITestsConfig.get('servers.kibana.port'); - const kerberosKeytabPath = resolve(__dirname, '../kerberos_api_integration/fixtures/krb5.keytab'); - const kerberosConfigPath = resolve(__dirname, '../kerberos_api_integration/fixtures/krb5.conf'); + const kerberosKeytabPath = resolve(__dirname, './fixtures/kerberos/krb5.keytab'); + const kerberosConfigPath = resolve(__dirname, './fixtures/kerberos/krb5.conf'); - const oidcJWKSPath = resolve(__dirname, '../oidc_api_integration/fixtures/jwks.json'); - const oidcIdPPlugin = resolve(__dirname, '../oidc_api_integration/fixtures/oidc_provider'); + const oidcJWKSPath = resolve(__dirname, './fixtures/oidc/jwks.json'); + const oidcIdPPlugin = resolve(__dirname, './fixtures/oidc/oidc_provider'); - const pkiKibanaCAPath = resolve(__dirname, '../pki_api_integration/fixtures/kibana_ca.crt'); + const pkiKibanaCAPath = resolve(__dirname, './fixtures/pki/kibana_ca.crt'); const saml1IdPMetadataPath = resolve(__dirname, './fixtures/saml/idp_metadata.xml'); const saml2IdPMetadataPath = resolve(__dirname, './fixtures/saml/idp_metadata_2.xml'); diff --git a/x-pack/test/oidc_api_integration/config.ts b/x-pack/test/security_api_integration/oidc.config.ts similarity index 89% rename from x-pack/test/oidc_api_integration/config.ts rename to x-pack/test/security_api_integration/oidc.config.ts index 08aa0a6d9c0dd..cb92282b40d32 100644 --- a/x-pack/test/oidc_api_integration/config.ts +++ b/x-pack/test/security_api_integration/oidc.config.ts @@ -10,17 +10,17 @@ import { services } from './services'; export default async function ({ readConfigFile }: FtrConfigProviderContext) { const xPackAPITestsConfig = await readConfigFile(require.resolve('../api_integration/config.ts')); - const plugin = resolve(__dirname, './fixtures/oidc_provider'); + const plugin = resolve(__dirname, './fixtures/oidc/oidc_provider'); const kibanaPort = xPackAPITestsConfig.get('servers.kibana.port'); - const jwksPath = resolve(__dirname, './fixtures/jwks.json'); + const jwksPath = resolve(__dirname, './fixtures/oidc/jwks.json'); return { - testFiles: [require.resolve('./apis/authorization_code_flow')], + testFiles: [require.resolve('./tests/oidc/authorization_code_flow')], servers: xPackAPITestsConfig.get('servers'), security: { disableTestUser: true }, services, junit: { - reportName: 'X-Pack OpenID Connect API Integration Tests', + reportName: 'X-Pack Security API Integration Tests (OIDC - Authorization Code Flow)', }, esTestCluster: { diff --git a/x-pack/test/oidc_api_integration/implicit_flow.config.ts b/x-pack/test/security_api_integration/oidc_implicit_flow.config.ts similarity index 88% rename from x-pack/test/oidc_api_integration/implicit_flow.config.ts rename to x-pack/test/security_api_integration/oidc_implicit_flow.config.ts index 992115d05c5a8..8907998f4df6d 100644 --- a/x-pack/test/oidc_api_integration/implicit_flow.config.ts +++ b/x-pack/test/security_api_integration/oidc_implicit_flow.config.ts @@ -7,14 +7,14 @@ import { FtrConfigProviderContext } from '@kbn/test/types/ftr'; export default async function ({ readConfigFile }: FtrConfigProviderContext) { - const oidcAPITestsConfig = await readConfigFile(require.resolve('./config.ts')); + const oidcAPITestsConfig = await readConfigFile(require.resolve('./oidc.config.ts')); return { ...oidcAPITestsConfig.getAll(), - testFiles: [require.resolve('./apis/implicit_flow')], + testFiles: [require.resolve('./tests/oidc/implicit_flow')], junit: { - reportName: 'X-Pack OpenID Connect API Integration Tests (Implicit Flow)', + reportName: 'X-Pack Security API Integration Tests (OIDC - Implicit Flow)', }, esTestCluster: { diff --git a/x-pack/test/pki_api_integration/config.ts b/x-pack/test/security_api_integration/pki.config.ts similarity index 93% rename from x-pack/test/pki_api_integration/config.ts rename to x-pack/test/security_api_integration/pki.config.ts index 5ce3111530dd9..1ce8bf9971fe0 100644 --- a/x-pack/test/pki_api_integration/config.ts +++ b/x-pack/test/security_api_integration/pki.config.ts @@ -25,12 +25,12 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { }; return { - testFiles: [require.resolve('./apis')], + testFiles: [require.resolve('./tests/pki')], servers, security: { disableTestUser: true }, services, junit: { - reportName: 'X-Pack PKI API Integration Tests', + reportName: 'X-Pack Security API Integration Tests (PKI)', }, esTestCluster: { @@ -58,7 +58,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { `--server.ssl.certificate=${KBN_CERT_PATH}`, `--server.ssl.certificateAuthorities=${JSON.stringify([ CA_CERT_PATH, - resolve(__dirname, './fixtures/kibana_ca.crt'), + resolve(__dirname, './fixtures/pki/kibana_ca.crt'), ])}`, `--server.ssl.clientAuthentication=required`, `--elasticsearch.hosts=${servers.elasticsearch.protocol}://${servers.elasticsearch.hostname}:${servers.elasticsearch.port}`, diff --git a/x-pack/test/security_api_integration/services.ts b/x-pack/test/security_api_integration/services.ts index a8d8048462693..73ec6fe396392 100644 --- a/x-pack/test/security_api_integration/services.ts +++ b/x-pack/test/security_api_integration/services.ts @@ -9,5 +9,6 @@ import { services as apiIntegrationServices } from '../api_integration/services' export const services = { ...commonServices, + esSupertest: apiIntegrationServices.esSupertest, supertestWithoutAuth: apiIntegrationServices.supertestWithoutAuth, }; diff --git a/x-pack/test/kerberos_api_integration/apis/security/index.ts b/x-pack/test/security_api_integration/tests/kerberos/index.ts similarity index 84% rename from x-pack/test/kerberos_api_integration/apis/security/index.ts rename to x-pack/test/security_api_integration/tests/kerberos/index.ts index 77a053ab14748..3fa2d155353a7 100644 --- a/x-pack/test/kerberos_api_integration/apis/security/index.ts +++ b/x-pack/test/security_api_integration/tests/kerberos/index.ts @@ -7,7 +7,9 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { - describe('security', () => { + describe('security APIs - Kerberos', function () { + this.tags('ciGroup6'); + loadTestFile(require.resolve('./kerberos_login')); }); } diff --git a/x-pack/test/kerberos_api_integration/apis/security/kerberos_login.ts b/x-pack/test/security_api_integration/tests/kerberos/kerberos_login.ts similarity index 95% rename from x-pack/test/kerberos_api_integration/apis/security/kerberos_login.ts rename to x-pack/test/security_api_integration/tests/kerberos/kerberos_login.ts index c31f6b689e972..e63f8cd2ebe32 100644 --- a/x-pack/test/kerberos_api_integration/apis/security/kerberos_login.ts +++ b/x-pack/test/security_api_integration/tests/kerberos/kerberos_login.ts @@ -11,7 +11,7 @@ import { FtrProviderContext } from '../../ftr_provider_context'; import { getMutualAuthenticationResponseToken, getSPNEGOToken, -} from '../../fixtures/kerberos_tools'; +} from '../../fixtures/kerberos/kerberos_tools'; export default function ({ getService }: FtrProviderContext) { const spnegoToken = getSPNEGOToken(); @@ -92,21 +92,21 @@ export default function ({ getService }: FtrProviderContext) { expect(spnegoResponse.headers['www-authenticate']).to.be('Negotiate'); }); - it('AJAX requests should properly initiate SPNEGO', async () => { + it('AJAX requests should not initiate SPNEGO', async () => { const ajaxResponse = await supertest .get('/abc/xyz/spnego?one=two three') .set('kbn-xsrf', 'xxx') .expect(401); expect(ajaxResponse.headers['set-cookie']).to.be(undefined); - expect(ajaxResponse.headers['www-authenticate']).to.be('Negotiate'); + expect(ajaxResponse.headers['www-authenticate']).to.be(undefined); }); }); describe('finishing SPNEGO', () => { it('should properly set cookie and authenticate user', async () => { const response = await supertest - .get('/internal/security/me') + .get('/security/account') .set('Authorization', `Negotiate ${spnegoToken}`) .expect(200); @@ -153,7 +153,7 @@ export default function ({ getService }: FtrProviderContext) { it('should re-initiate SPNEGO handshake if token is rejected with 401', async () => { const spnegoResponse = await supertest - .get('/internal/security/me') + .get('/security/account') .set('Authorization', `Negotiate ${Buffer.from('Hello').toString('base64')}`) .expect(401); expect(spnegoResponse.headers['set-cookie']).to.be(undefined); @@ -162,7 +162,7 @@ export default function ({ getService }: FtrProviderContext) { it('should fail if SPNEGO token is rejected because of unknown reason', async () => { const spnegoResponse = await supertest - .get('/internal/security/me') + .get('/security/account') .set('Authorization', 'Negotiate (:I am malformed:)') .expect(500); expect(spnegoResponse.headers['set-cookie']).to.be(undefined); @@ -175,7 +175,7 @@ export default function ({ getService }: FtrProviderContext) { beforeEach(async () => { const response = await supertest - .get('/internal/security/me') + .get('/security/account') .set('Authorization', `Negotiate ${spnegoToken}`) .expect(200); @@ -239,7 +239,7 @@ export default function ({ getService }: FtrProviderContext) { it('should redirect to `logged_out` page after successful logout', async () => { // First authenticate user to retrieve session cookie. const response = await supertest - .get('/internal/security/me') + .get('/security/account') .set('Authorization', `Negotiate ${spnegoToken}`) .expect(200); @@ -274,7 +274,9 @@ export default function ({ getService }: FtrProviderContext) { expect(cookies).to.have.length(1); checkCookieIsCleared(request.cookie(cookies[0])!); - expect(apiResponse.headers['www-authenticate']).to.be('Negotiate'); + // Request with a session cookie that is linked to an invalidated/non-existent session is treated the same as + // request without any session cookie at all. + expect(apiResponse.headers['www-authenticate']).to.be(undefined); }); it('should redirect to home page if session cookie is not provided', async () => { @@ -290,7 +292,7 @@ export default function ({ getService }: FtrProviderContext) { beforeEach(async () => { const response = await supertest - .get('/internal/security/me') + .get('/security/account') .set('Authorization', `Negotiate ${spnegoToken}`) .expect(200); @@ -342,7 +344,7 @@ export default function ({ getService }: FtrProviderContext) { // This request should succeed and automatically refresh token. Returned cookie will contain // the new access and refresh token pair. const nonAjaxResponse = await supertest - .get('/app/kibana') + .get('/security/account') .set('Cookie', sessionCookie.cookieString()) .expect(200); @@ -368,7 +370,7 @@ export default function ({ getService }: FtrProviderContext) { beforeEach(async () => { const response = await supertest - .get('/internal/security/me') + .get('/security/account') .set('Authorization', `Negotiate ${spnegoToken}`) .expect(200); @@ -405,7 +407,7 @@ export default function ({ getService }: FtrProviderContext) { it('non-AJAX call should initiate SPNEGO and clear existing cookie', async function () { const nonAjaxResponse = await supertest - .get('/') + .get('/security/account') .set('Cookie', sessionCookie.cookieString()) .expect(401); diff --git a/x-pack/test/security_api_integration/tests/login_selector/basic_functionality.ts b/x-pack/test/security_api_integration/tests/login_selector/basic_functionality.ts index 432fd6ff91280..cf141972b044a 100644 --- a/x-pack/test/security_api_integration/tests/login_selector/basic_functionality.ts +++ b/x-pack/test/security_api_integration/tests/login_selector/basic_functionality.ts @@ -11,11 +11,11 @@ import url from 'url'; import { CA_CERT_PATH } from '@kbn/dev-utils'; import expect from '@kbn/expect'; import type { AuthenticationProvider } from '../../../../plugins/security/common/types'; -import { getStateAndNonce } from '../../../oidc_api_integration/fixtures/oidc_tools'; +import { getStateAndNonce } from '../../fixtures/oidc/oidc_tools'; import { getMutualAuthenticationResponseToken, getSPNEGOToken, -} from '../../../kerberos_api_integration/fixtures/kerberos_tools'; +} from '../../fixtures/kerberos/kerberos_tools'; import { getSAMLRequestId, getSAMLResponse } from '../../fixtures/saml/saml_tools'; import { FtrProviderContext } from '../../ftr_provider_context'; @@ -29,9 +29,7 @@ export default function ({ getService }: FtrProviderContext) { const validPassword = kibanaServerConfig.password; const CA_CERT = readFileSync(CA_CERT_PATH); - const CLIENT_CERT = readFileSync( - resolve(__dirname, '../../../pki_api_integration/fixtures/first_client.p12') - ); + const CLIENT_CERT = readFileSync(resolve(__dirname, '../../fixtures/pki/first_client.p12')); async function checkSessionCookie( sessionCookie: Cookie, diff --git a/x-pack/test/oidc_api_integration/apis/authorization_code_flow/index.ts b/x-pack/test/security_api_integration/tests/oidc/authorization_code_flow/index.ts similarity index 73% rename from x-pack/test/oidc_api_integration/apis/authorization_code_flow/index.ts rename to x-pack/test/security_api_integration/tests/oidc/authorization_code_flow/index.ts index 0acae074f129f..4def5388abae0 100644 --- a/x-pack/test/oidc_api_integration/apis/authorization_code_flow/index.ts +++ b/x-pack/test/security_api_integration/tests/oidc/authorization_code_flow/index.ts @@ -4,10 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { - describe('apis', function () { + describe('security APIs - OIDC (Authorization Code Flow)', function () { this.tags('ciGroup6'); loadTestFile(require.resolve('./oidc_auth')); }); diff --git a/x-pack/test/oidc_api_integration/apis/authorization_code_flow/oidc_auth.ts b/x-pack/test/security_api_integration/tests/oidc/authorization_code_flow/oidc_auth.ts similarity index 99% rename from x-pack/test/oidc_api_integration/apis/authorization_code_flow/oidc_auth.ts rename to x-pack/test/security_api_integration/tests/oidc/authorization_code_flow/oidc_auth.ts index 1fdb15a86ce0a..aac41374734b2 100644 --- a/x-pack/test/oidc_api_integration/apis/authorization_code_flow/oidc_auth.ts +++ b/x-pack/test/security_api_integration/tests/oidc/authorization_code_flow/oidc_auth.ts @@ -8,8 +8,8 @@ import expect from '@kbn/expect'; import request, { Cookie } from 'request'; import url from 'url'; import { delay } from 'bluebird'; -import { getStateAndNonce } from '../../fixtures/oidc_tools'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { getStateAndNonce } from '../../../fixtures/oidc/oidc_tools'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { const supertest = getService('supertestWithoutAuth'); diff --git a/x-pack/test/oidc_api_integration/apis/implicit_flow/index.ts b/x-pack/test/security_api_integration/tests/oidc/implicit_flow/index.ts similarity index 74% rename from x-pack/test/oidc_api_integration/apis/implicit_flow/index.ts rename to x-pack/test/security_api_integration/tests/oidc/implicit_flow/index.ts index 0acae074f129f..0441d14b9196d 100644 --- a/x-pack/test/oidc_api_integration/apis/implicit_flow/index.ts +++ b/x-pack/test/security_api_integration/tests/oidc/implicit_flow/index.ts @@ -4,10 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { - describe('apis', function () { + describe('security APIs - OIDC (Implicit Flow)', function () { this.tags('ciGroup6'); loadTestFile(require.resolve('./oidc_auth')); }); diff --git a/x-pack/test/oidc_api_integration/apis/implicit_flow/oidc_auth.ts b/x-pack/test/security_api_integration/tests/oidc/implicit_flow/oidc_auth.ts similarity index 97% rename from x-pack/test/oidc_api_integration/apis/implicit_flow/oidc_auth.ts rename to x-pack/test/security_api_integration/tests/oidc/implicit_flow/oidc_auth.ts index 7c408d8b903e3..ced9598809e10 100644 --- a/x-pack/test/oidc_api_integration/apis/implicit_flow/oidc_auth.ts +++ b/x-pack/test/security_api_integration/tests/oidc/implicit_flow/oidc_auth.ts @@ -8,8 +8,8 @@ import expect from '@kbn/expect'; import { JSDOM } from 'jsdom'; import request, { Cookie } from 'request'; import { format as formatURL } from 'url'; -import { createTokens, getStateAndNonce } from '../../fixtures/oidc_tools'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { createTokens, getStateAndNonce } from '../../../fixtures/oidc/oidc_tools'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { const supertest = getService('supertestWithoutAuth'); diff --git a/x-pack/test/pki_api_integration/apis/security/index.ts b/x-pack/test/security_api_integration/tests/pki/index.ts similarity index 85% rename from x-pack/test/pki_api_integration/apis/security/index.ts rename to x-pack/test/security_api_integration/tests/pki/index.ts index 63dca75d075fa..380335ba25f84 100644 --- a/x-pack/test/pki_api_integration/apis/security/index.ts +++ b/x-pack/test/security_api_integration/tests/pki/index.ts @@ -7,7 +7,9 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { - describe('security', () => { + describe('security APIs - PKI', function () { + this.tags('ciGroup6'); + loadTestFile(require.resolve('./pki_auth')); }); } diff --git a/x-pack/test/pki_api_integration/apis/security/pki_auth.ts b/x-pack/test/security_api_integration/tests/pki/pki_auth.ts similarity index 90% rename from x-pack/test/pki_api_integration/apis/security/pki_auth.ts rename to x-pack/test/security_api_integration/tests/pki/pki_auth.ts index 43b728d12311d..0331f756712ca 100644 --- a/x-pack/test/pki_api_integration/apis/security/pki_auth.ts +++ b/x-pack/test/security_api_integration/tests/pki/pki_auth.ts @@ -13,10 +13,10 @@ import { CA_CERT_PATH } from '@kbn/dev-utils'; import { FtrProviderContext } from '../../ftr_provider_context'; const CA_CERT = readFileSync(CA_CERT_PATH); -const FIRST_CLIENT_CERT = readFileSync(resolve(__dirname, '../../fixtures/first_client.p12')); -const SECOND_CLIENT_CERT = readFileSync(resolve(__dirname, '../../fixtures/second_client.p12')); +const FIRST_CLIENT_CERT = readFileSync(resolve(__dirname, '../../fixtures/pki/first_client.p12')); +const SECOND_CLIENT_CERT = readFileSync(resolve(__dirname, '../../fixtures/pki/second_client.p12')); const UNTRUSTED_CLIENT_CERT = readFileSync( - resolve(__dirname, '../../fixtures/untrusted_client.p12') + resolve(__dirname, '../../fixtures/pki/untrusted_client.p12') ); export default function ({ getService }: FtrProviderContext) { @@ -97,9 +97,20 @@ export default function ({ getService }: FtrProviderContext) { // Do not assert on the `authentication_realm`, as the value differs for on-prem vs cloud }); + it('AJAX requests should not create a new session', async () => { + const ajaxResponse = await supertest + .get('/internal/security/me') + .set('kbn-xsrf', 'xxx') + .ca(CA_CERT) + .pfx(FIRST_CLIENT_CERT) + .expect(401); + + expect(ajaxResponse.headers['set-cookie']).to.be(undefined); + }); + it('should properly set cookie and authenticate user', async () => { const response = await supertest - .get('/internal/security/me') + .get('/security/account') .ca(CA_CERT) .pfx(FIRST_CLIENT_CERT) .expect(200); @@ -110,35 +121,34 @@ export default function ({ getService }: FtrProviderContext) { const sessionCookie = request.cookie(cookies[0])!; checkCookieIsSet(sessionCookie); - expect(response.body).to.eql({ - username: 'first_client', - roles: ['kibana_admin'], - full_name: null, - email: null, - enabled: true, - metadata: { - pki_delegated_by_realm: 'reserved', - pki_delegated_by_user: 'kibana', - pki_dn: 'CN=first_client', - }, - authentication_realm: { name: 'pki1', type: 'pki' }, - lookup_realm: { name: 'pki1', type: 'pki' }, - authentication_provider: { name: 'pki', type: 'pki' }, - authentication_type: 'token', - }); - // Cookie should be accepted. await supertest .get('/internal/security/me') + .set('kbn-xsrf', 'xxx') .ca(CA_CERT) .pfx(FIRST_CLIENT_CERT) .set('Cookie', sessionCookie.cookieString()) - .expect(200); + .expect(200, { + username: 'first_client', + roles: ['kibana_admin'], + full_name: null, + email: null, + enabled: true, + metadata: { + pki_delegated_by_realm: 'reserved', + pki_delegated_by_user: 'kibana', + pki_dn: 'CN=first_client', + }, + authentication_realm: { name: 'pki1', type: 'pki' }, + lookup_realm: { name: 'pki1', type: 'pki' }, + authentication_provider: { name: 'pki', type: 'pki' }, + authentication_type: 'token', + }); }); it('should update session if new certificate is provided', async () => { let response = await supertest - .get('/internal/security/me') + .get('/security/account') .ca(CA_CERT) .pfx(FIRST_CLIENT_CERT) .expect(200); @@ -177,7 +187,7 @@ export default function ({ getService }: FtrProviderContext) { it('should reject valid cookie if used with untrusted certificate', async () => { const response = await supertest - .get('/internal/security/me') + .get('/security/account') .ca(CA_CERT) .pfx(FIRST_CLIENT_CERT) .expect(200); @@ -201,7 +211,7 @@ export default function ({ getService }: FtrProviderContext) { beforeEach(async () => { const response = await supertest - .get('/internal/security/me') + .get('/security/account') .ca(CA_CERT) .pfx(FIRST_CLIENT_CERT) .expect(200); @@ -274,7 +284,7 @@ export default function ({ getService }: FtrProviderContext) { it('should redirect to `logged_out` page after successful logout', async () => { // First authenticate user to retrieve session cookie. const response = await supertest - .get('/internal/security/me') + .get('/security/account') .ca(CA_CERT) .pfx(FIRST_CLIENT_CERT) .expect(200); @@ -317,7 +327,7 @@ export default function ({ getService }: FtrProviderContext) { beforeEach(async () => { const response = await supertest - .get('/internal/security/me') + .get('/security/account') .ca(CA_CERT) .pfx(FIRST_CLIENT_CERT) .expect(200); @@ -363,7 +373,7 @@ export default function ({ getService }: FtrProviderContext) { // This request should succeed and automatically refresh token. Returned cookie will contain // the new access and refresh token pair. const nonAjaxResponse = await supertest - .get('/app/kibana') + .get('/security/account') .ca(CA_CERT) .pfx(FIRST_CLIENT_CERT) .set('Cookie', sessionCookie.cookieString()) diff --git a/x-pack/test/security_functional/oidc.config.ts b/x-pack/test/security_functional/oidc.config.ts index 1ed5d51098420..add6f0f164b3a 100644 --- a/x-pack/test/security_functional/oidc.config.ts +++ b/x-pack/test/security_functional/oidc.config.ts @@ -20,8 +20,11 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { ); const kibanaPort = kibanaFunctionalConfig.get('servers.kibana.port'); - const jwksPath = resolve(__dirname, '../oidc_api_integration/fixtures/jwks.json'); - const oidcOpPPlugin = resolve(__dirname, '../oidc_api_integration/fixtures/oidc_provider'); + const jwksPath = resolve(__dirname, '../security_api_integration/fixtures/oidc/jwks.json'); + const oidcOpPPlugin = resolve( + __dirname, + '../security_api_integration/fixtures/oidc/oidc_provider' + ); return { testFiles: [resolve(__dirname, './tests/oidc')], diff --git a/x-pack/test/security_solution_endpoint/apps/endpoint/index.ts b/x-pack/test/security_solution_endpoint/apps/endpoint/index.ts index 3e3aeee305433..3103d461669f1 100644 --- a/x-pack/test/security_solution_endpoint/apps/endpoint/index.ts +++ b/x-pack/test/security_solution_endpoint/apps/endpoint/index.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { getRegistryUrl as getRegistryUrlFromIngest } from '../../../../plugins/ingest_manager/server'; +import { getRegistryUrl as getRegistryUrlFromIngest } from '../../../../plugins/fleet/server'; import { FtrProviderContext } from '../../ftr_provider_context'; import { isRegistryEnabled, diff --git a/x-pack/test/security_solution_endpoint/apps/endpoint/resolver.ts b/x-pack/test/security_solution_endpoint/apps/endpoint/resolver.ts index b45c082423628..d49f5bf17aab1 100644 --- a/x-pack/test/security_solution_endpoint/apps/endpoint/resolver.ts +++ b/x-pack/test/security_solution_endpoint/apps/endpoint/resolver.ts @@ -279,6 +279,29 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { } await pageObjects.hosts.runNodeEvents(expectedLibraryData); }); + + it('Check Related Events for event.alert Node', async () => { + await esArchiver.load('empty_kibana'); + await esArchiver.load('endpoint/resolver_tree/alert_events', { useCreate: true }); + await queryBar.setQuery(''); + await queryBar.submitQuery(); + const expectedAlertData = [ + '1 library', + '157 file', + '520 registry', + '3 file', + '5 library', + '5 library', + ]; + await pageObjects.hosts.navigateToEventsPanel(); + await pageObjects.hosts.executeQueryAndOpenResolver('event.dataset : endpoint.alerts'); + await (await testSubjects.find('resolver:graph-controls:zoom-out')).click(); + await browser.setWindowSize(2100, 1500); + for (let i = 0; i < 2; i++) { + await (await testSubjects.find('resolver:graph-controls:east-button')).click(); + } + await pageObjects.hosts.runNodeEvents(expectedAlertData); + }); }); }); } diff --git a/x-pack/test/security_solution_endpoint/config.ts b/x-pack/test/security_solution_endpoint/config.ts index 9ee9e061edf4c..9499c235a5f0d 100644 --- a/x-pack/test/security_solution_endpoint/config.ts +++ b/x-pack/test/security_solution_endpoint/config.ts @@ -30,7 +30,6 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { ['securitySolutionManagement']: { pathname: '/app/security/administration', }, - ...xpackFunctionalConfig.get('apps'), ['security']: { pathname: '/app/security', }, diff --git a/x-pack/test/security_solution_endpoint/page_objects/hosts_page.ts b/x-pack/test/security_solution_endpoint/page_objects/hosts_page.ts index 988fadbbdfe33..c76a5a7c22f60 100644 --- a/x-pack/test/security_solution_endpoint/page_objects/hosts_page.ts +++ b/x-pack/test/security_solution_endpoint/page_objects/hosts_page.ts @@ -121,6 +121,8 @@ export function SecurityHostsPageProvider({ getService, getPageObjects }: FtrPro for (let i = 0; i < NodeSubmenuItems.length; i++) { await (await testSubjects.findAll('resolver:map:node-submenu-item'))[i].click(); const Events = await testSubjects.findAll('resolver:map:node-submenu-item'); + // this sleep is for the AMP enabled run + await pageObjects.common.sleep(300); const EventName = await Events[i]._webElement.getText(); const LinkText = await testSubjects.find('resolver:breadcrumbs:last'); const linkText = await LinkText._webElement.getText(); diff --git a/x-pack/test/security_solution_endpoint/services/endpoint_policy.ts b/x-pack/test/security_solution_endpoint/services/endpoint_policy.ts index 7fc51f5c8e39c..1b1d0bf96a187 100644 --- a/x-pack/test/security_solution_endpoint/services/endpoint_policy.ts +++ b/x-pack/test/security_solution_endpoint/services/endpoint_policy.ts @@ -15,7 +15,7 @@ import { GetPackagePoliciesResponse, GetFullAgentPolicyResponse, GetPackagesResponse, -} from '../../../plugins/ingest_manager/common'; +} from '../../../plugins/fleet/common'; import { factory as policyConfigFactory } from '../../../plugins/security_solution/common/endpoint/models/policy_config'; import { Immutable } from '../../../plugins/security_solution/common/endpoint/types'; diff --git a/x-pack/test/security_solution_endpoint_api_int/apis/index.ts b/x-pack/test/security_solution_endpoint_api_int/apis/index.ts index 3d344c1b3b51b..cd0a861d9a2f0 100644 --- a/x-pack/test/security_solution_endpoint_api_int/apis/index.ts +++ b/x-pack/test/security_solution_endpoint_api_int/apis/index.ts @@ -5,7 +5,7 @@ */ import { FtrProviderContext } from '../ftr_provider_context'; import { isRegistryEnabled, getRegistryUrlFromTestEnv } from '../registry'; -import { getRegistryUrl as getRegistryUrlFromIngest } from '../../../plugins/ingest_manager/server'; +import { getRegistryUrl as getRegistryUrlFromIngest } from '../../../plugins/fleet/server'; export default function endpointAPIIntegrationTests(providerContext: FtrProviderContext) { const { loadTestFile, getService } = providerContext; diff --git a/yarn.lock b/yarn.lock index 0b429c96c1847..b59c134968c18 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1310,7 +1310,7 @@ tunnel-agent "^0.6.0" uuid "^3.3.2" -"@cypress/snapshot@^2.1.3": +"@cypress/snapshot@^2.1.7": version "2.1.7" resolved "https://registry.yarnpkg.com/@cypress/snapshot/-/snapshot-2.1.7.tgz#e7360eb628b062f28f03036382619ec72cfb1831" integrity sha512-f8AcfIg7wOOHSdBODlIwCJE/rG5Yb+kUY+WVTKynB2pLLoDy9nc8CtcazqX19q2Lh++nTJLNRihpbbWvk33mbg== @@ -1324,10 +1324,10 @@ snap-shot-compare "2.8.3" snap-shot-store "1.2.3" -"@cypress/webpack-preprocessor@^5.4.1": - version "5.4.6" - resolved "https://registry.yarnpkg.com/@cypress/webpack-preprocessor/-/webpack-preprocessor-5.4.6.tgz#667f8007cbe6ee219ce7e45a7f1400d3e2401032" - integrity sha512-78hWoTUUEncv647badwVbyszvmwI1r9GaY/xy7V0sz0VVC90ByuDkLpvN+J0VP6enthob4dIPXcm0f9Tb1UKQQ== +"@cypress/webpack-preprocessor@^5.4.10": + version "5.4.10" + resolved "https://registry.yarnpkg.com/@cypress/webpack-preprocessor/-/webpack-preprocessor-5.4.10.tgz#ed0a3ed495f5455899f7c567830b37477c3f26f5" + integrity sha512-6j809mAQcZsAbpIaQFlKwFQPKv1Y+ZyLr9bpW7d2utMGVll0W8Up4RPhIuAf4q9Tx+DOBQoiCpy/n0cRPxporw== dependencies: bluebird "^3.7.1" debug "^4.1.1" @@ -9094,7 +9094,7 @@ chai@^4.1.2: pathval "^1.1.0" type-detect "^4.0.5" -chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.1, chalk@^2.3.2, chalk@^2.4.1, chalk@^2.4.2, chalk@~2.4.1: +chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.1, chalk@^2.3.2, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -9122,7 +9122,7 @@ chalk@^3.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -chalk@^4.0.0, chalk@^4.1.0: +chalk@^4.0.0, chalk@^4.1.0, chalk@~4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== @@ -9690,11 +9690,6 @@ coffeescript@1.12.7: resolved "https://registry.yarnpkg.com/coffeescript/-/coffeescript-1.12.7.tgz#e57ee4c4867cf7f606bfc4a0f2d550c0981ddd27" integrity sha512-pLXHFxQMPklVoEekowk8b3erNynC+DVJzChxS/LCBBgR6/8AJkHivkm//zbowcfc7BTCAjryuhx6gPqPRfsFoA== -coffeescript@~1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/coffeescript/-/coffeescript-1.10.0.tgz#e7aa8301917ef621b35d8a39f348dcdd1db7e33e" - integrity sha1-56qDAZF+9iGzXYo580jc3R234z4= - collapse-white-space@^1.0.0, collapse-white-space@^1.0.2: version "1.0.6" resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-1.0.6.tgz#e63629c0016665792060dbbeb79c42239d2c5287" @@ -10711,23 +10706,23 @@ cypress-cucumber-preprocessor@^2.5.2: minimist "^1.2.0" through "^2.3.8" -cypress-multi-reporters@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/cypress-multi-reporters/-/cypress-multi-reporters-1.2.3.tgz#4ba39373631c6521d21931d73f6b0bafa1ccbf83" - integrity sha512-W3ItWsbSgMfsQFTuB89OXY5gyqLuM0O2lNEn+mcQAYeMs36TxVLAg3q+Hk0Om+NcWj8OLhM06lBQpnu9+i4gug== +cypress-multi-reporters@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/cypress-multi-reporters/-/cypress-multi-reporters-1.4.0.tgz#5f1d0484a20959cfe782f1bf65ad16c6ad804da7" + integrity sha512-CjpQduW43KVzY45hhKC/qf8MSebRpx6JyEz6py8F+0GrYS8rE5TZ8wXv9dPUs/PaT6w+dR8KIgLSMr967Om7iA== dependencies: debug "^4.1.1" - lodash "^4.17.11" + lodash "^4.17.15" cypress-promise@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/cypress-promise/-/cypress-promise-1.1.0.tgz#f2d66965945fe198431aaf692d5157cea9d47b25" integrity sha512-DhIf5PJ/a0iY+Yii6n7Rbwq+9TJxU4pupXYzf9mZd8nPG0AzQrj9i+pqINv4xbI2EV1p+PKW3maCkR7oPG4GrA== -cypress@^5.4.0: - version "5.4.0" - resolved "https://registry.yarnpkg.com/cypress/-/cypress-5.4.0.tgz#8833a76e91129add601f823d43c53eb512d162c5" - integrity sha512-BJR+u3DRSYMqaBS1a3l1rbh5AkMRHugbxcYYzkl+xYlO6dzcJVE8uAhghzVI/hxijCyBg1iuSe4TRp/g1PUg8Q== +cypress@^5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/cypress/-/cypress-5.5.0.tgz#1da0355794a43247f8a80cb7f505e83e1cf847cb" + integrity sha512-UHEiTca8AUTevbT2pWkHQlxoHtXmbq+h6Eiu/Mz8DqpNkF98zjTBLv/HFiKJUU5rQzp9EwSWtms33p5TWCJ8tQ== dependencies: "@cypress/listr-verbose-renderer" "^0.4.1" "@cypress/request" "^2.88.5" @@ -10759,10 +10754,10 @@ cypress@^5.4.0: minimist "^1.2.5" moment "^2.27.0" ospath "^1.2.2" - pretty-bytes "^5.3.0" + pretty-bytes "^5.4.1" ramda "~0.26.1" request-progress "^3.0.0" - supports-color "^7.1.0" + supports-color "^7.2.0" tmp "~0.2.1" untildify "^4.0.0" url "^0.11.0" @@ -11103,7 +11098,7 @@ date-now@^0.1.4: resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" integrity sha1-6vQ5/U1ISK105cx9vvIAZyueNFs= -dateformat@^1.0.11, dateformat@~1.0.12: +dateformat@^1.0.11: version "1.0.12" resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-1.0.12.tgz#9f124b67594c937ff706932e4a642cca8dbbfee9" integrity sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk= @@ -11111,7 +11106,7 @@ dateformat@^1.0.11, dateformat@~1.0.12: get-stdin "^4.0.1" meow "^3.3.0" -dateformat@^3.0.2: +dateformat@^3.0.2, dateformat@~3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== @@ -12704,10 +12699,10 @@ eslint-plugin-ban@^1.4.0: dependencies: requireindex "~1.2.0" -eslint-plugin-cypress@^2.8.1: - version "2.8.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-cypress/-/eslint-plugin-cypress-2.8.1.tgz#981a0f3658b40de430bcf05cabc96b396487c91f" - integrity sha512-jDpcP+MmjmqQO/x3bwIXgp4cl7Q66RYS5/IsuOQP4Qo2sEqE3DI8tTxBQ1EhnV5qEDd2Z2TYHR+5vYI6oCN4uw== +eslint-plugin-cypress@^2.11.2: + version "2.11.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-cypress/-/eslint-plugin-cypress-2.11.2.tgz#a8f3fe7ec840f55e4cea37671f93293e6c3e76a0" + integrity sha512-1SergF1sGbVhsf7MYfOLiBhdOg6wqyeV9pXUAIDIffYTGMN3dTBQS9nFAzhLsHhO+Bn0GaVM1Ecm71XUidQ7VA== dependencies: globals "^11.12.0" @@ -13151,7 +13146,7 @@ exit-hook@^2.2.0: resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-2.2.0.tgz#f5502f92179018e867f2d8ee4428392da7f3894e" integrity sha512-YFH+2oGdldRH5GqGpnaiKbBxWHMmuXHmKTMtUC58kWSOrnTf95rKITVSFTTtas14DWvWpih429+ffAvFetPwNA== -exit@^0.1.2, exit@~0.1.1: +exit@^0.1.2, exit@~0.1.1, exit@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw= @@ -14586,7 +14581,7 @@ glob@^6.0.1, glob@^6.0.4: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.0.0, glob@^7.0.3, glob@^7.1.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@~7.1.1, glob@~7.1.4: +glob@^7.0.0, glob@^7.0.3, glob@^7.1.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@~7.1.1, glob@~7.1.4, glob@~7.1.6: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== @@ -14609,18 +14604,6 @@ glob@~5.0.0: once "^1.3.0" path-is-absolute "^1.0.0" -glob@~7.0.0: - version "7.0.6" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.0.6.tgz#211bafaf49e525b8cd93260d14ab136152b3f57a" - integrity sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo= - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.2" - once "^1.3.0" - path-is-absolute "^1.0.0" - global-dirs@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-2.0.1.tgz#acdf3bb6685bcd55cb35e8a052266569e9469201" @@ -15165,15 +15148,16 @@ grunt-babel@^8.0.0: resolved "https://registry.yarnpkg.com/grunt-babel/-/grunt-babel-8.0.0.tgz#92ef63aafadf938c488dc2f926ac9846e0c93d1b" integrity sha512-WuiZFvGzcyzlEoPIcY1snI234ydDWeWWV5bpnB7PZsOLHcDsxWKnrR1rMWEUsbdVPPjvIirwFNsuo4CbJmsdFQ== -grunt-cli@^1.2.0, grunt-cli@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/grunt-cli/-/grunt-cli-1.2.0.tgz#562b119ebb069ddb464ace2845501be97b35b6a8" - integrity sha1-VisRnrsGndtGSs4oRVAb6Xs1tqg= +grunt-cli@~1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/grunt-cli/-/grunt-cli-1.3.2.tgz#60f12d12c1b5aae94ae3469c6b5fe24e960014e8" + integrity sha512-8OHDiZZkcptxVXtMfDxJvmN7MVJNE8L/yIcPb4HB7TlyFD1kDvjHrb62uhySsU14wJx9ORMnTuhRMQ40lH/orQ== dependencies: - findup-sync "~0.3.0" grunt-known-options "~1.1.0" - nopt "~3.0.6" - resolve "~1.1.0" + interpret "~1.1.0" + liftoff "~2.5.0" + nopt "~4.0.1" + v8flags "~3.1.1" grunt-contrib-clean@^1.1.0: version "1.1.0" @@ -15206,35 +15190,35 @@ grunt-known-options@~1.1.0: resolved "https://registry.yarnpkg.com/grunt-known-options/-/grunt-known-options-1.1.0.tgz#a4274eeb32fa765da5a7a3b1712617ce3b144149" integrity sha1-pCdO6zL6dl2lp6OxcSYXzjsUQUk= -grunt-legacy-log-utils@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/grunt-legacy-log-utils/-/grunt-legacy-log-utils-2.0.1.tgz#d2f442c7c0150065d9004b08fd7410d37519194e" - integrity sha512-o7uHyO/J+i2tXG8r2bZNlVk20vlIFJ9IEYyHMCQGfWYru8Jv3wTqKZzvV30YW9rWEjq0eP3cflQ1qWojIe9VFA== +grunt-legacy-log-utils@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/grunt-legacy-log-utils/-/grunt-legacy-log-utils-2.1.0.tgz#49a8c7dc74051476dcc116c32faf9db8646856ef" + integrity sha512-lwquaPXJtKQk0rUM1IQAop5noEpwFqOXasVoedLeNzaibf/OPWjKYvvdqnEHNmU+0T0CaReAXIbGo747ZD+Aaw== dependencies: - chalk "~2.4.1" - lodash "~4.17.10" + chalk "~4.1.0" + lodash "~4.17.19" -grunt-legacy-log@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/grunt-legacy-log/-/grunt-legacy-log-2.0.0.tgz#c8cd2c6c81a4465b9bbf2d874d963fef7a59ffb9" - integrity sha512-1m3+5QvDYfR1ltr8hjiaiNjddxGdQWcH0rw1iKKiQnF0+xtgTazirSTGu68RchPyh1OBng1bBUjLmX8q9NpoCw== +grunt-legacy-log@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/grunt-legacy-log/-/grunt-legacy-log-3.0.0.tgz#1c6eaf92371ea415af31ea84ce50d434ef6d39c4" + integrity sha512-GHZQzZmhyq0u3hr7aHW4qUH0xDzwp2YXldLPZTCjlOeGscAOWWPftZG3XioW8MasGp+OBRIu39LFx14SLjXRcA== dependencies: colors "~1.1.2" - grunt-legacy-log-utils "~2.0.0" + grunt-legacy-log-utils "~2.1.0" hooker "~0.2.3" - lodash "~4.17.5" + lodash "~4.17.19" -grunt-legacy-util@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/grunt-legacy-util/-/grunt-legacy-util-1.1.1.tgz#e10624e7c86034e5b870c8a8616743f0a0845e42" - integrity sha512-9zyA29w/fBe6BIfjGENndwoe1Uy31BIXxTH3s8mga0Z5Bz2Sp4UCjkeyv2tI449ymkx3x26B+46FV4fXEddl5A== +grunt-legacy-util@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/grunt-legacy-util/-/grunt-legacy-util-2.0.0.tgz#34d20f2a26c6adebfe9a9bdc8823f7016b0369c3" + integrity sha512-ZEmYFB44bblwPE2oz3q3ygfF6hseQja9tx8I3UZIwbUik32FMWewA+d1qSFicMFB+8dNXDkh35HcDCWlpRsGlA== dependencies: async "~1.5.2" exit "~0.1.1" getobject "~0.1.0" hooker "~0.2.3" - lodash "~4.17.10" - underscore.string "~3.3.4" + lodash "~4.17.20" + underscore.string "~3.3.5" which "~1.3.0" grunt-peg@^2.0.1: @@ -15251,28 +15235,26 @@ grunt-run@0.8.1: dependencies: strip-ansi "^3.0.0" -grunt@1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/grunt/-/grunt-1.0.4.tgz#c799883945a53a3d07622e0737c8f70bfe19eb38" - integrity sha512-PYsMOrOC+MsdGEkFVwMaMyc6Ob7pKmq+deg1Sjr+vvMWp35sztfwKE7qoN51V+UEtHsyNuMcGdgMLFkBHvMxHQ== +grunt@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/grunt/-/grunt-1.3.0.tgz#55db6ccd80c6fb53722e496f680620a2e681f809" + integrity sha512-6ILlMXv11/4cxuhSMfSU+SfvbxrPuqZrAtLN64+tZpQ3DAKfSQPQHRbTjSbdtxfyQhGZPtN0bDZJ/LdCM5WXXA== dependencies: - coffeescript "~1.10.0" - dateformat "~1.0.12" + dateformat "~3.0.3" eventemitter2 "~0.4.13" - exit "~0.1.1" + exit "~0.1.2" findup-sync "~0.3.0" - glob "~7.0.0" - grunt-cli "~1.2.0" + glob "~7.1.6" + grunt-cli "~1.3.2" grunt-known-options "~1.1.0" - grunt-legacy-log "~2.0.0" - grunt-legacy-util "~1.1.1" + grunt-legacy-log "~3.0.0" + grunt-legacy-util "~2.0.0" iconv-lite "~0.4.13" - js-yaml "~3.13.0" - minimatch "~3.0.2" - mkdirp "~0.5.1" + js-yaml "~3.14.0" + minimatch "~3.0.4" + mkdirp "~1.0.4" nopt "~3.0.6" - path-is-absolute "~1.0.0" - rimraf "~2.6.2" + rimraf "~3.0.2" gud@^1.0.0: version "1.0.0" @@ -16431,6 +16413,11 @@ interpret@^2.0.0: resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9" integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw== +interpret@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614" + integrity sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ= + intl-format-cache@^2.0.5, intl-format-cache@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/intl-format-cache/-/intl-format-cache-2.1.0.tgz#04a369fecbfad6da6005bae1f14333332dcf9316" @@ -18070,7 +18057,7 @@ js-tokens@^4.0.0: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@3.13.1, js-yaml@^3.10.0, js-yaml@^3.13.1, js-yaml@^3.4.6, js-yaml@^3.5.1, js-yaml@^3.5.4, js-yaml@^3.9.0, js-yaml@~3.13.0, js-yaml@~3.13.1: +js-yaml@3.13.1, js-yaml@^3.10.0, js-yaml@^3.13.1, js-yaml@^3.4.6, js-yaml@^3.5.1, js-yaml@^3.5.4, js-yaml@^3.9.0, js-yaml@~3.13.1: version "3.13.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== @@ -18078,7 +18065,7 @@ js-yaml@3.13.1, js-yaml@^3.10.0, js-yaml@^3.13.1, js-yaml@^3.4.6, js-yaml@^3.5.1 argparse "^1.0.7" esprima "^4.0.0" -js-yaml@^3.14.0: +js-yaml@^3.14.0, js-yaml@~3.14.0: version "3.14.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.0.tgz#a7a34170f26a21bb162424d8adacb4113a69e482" integrity sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A== @@ -18715,6 +18702,20 @@ liftoff@^3.1.0: rechoir "^0.6.2" resolve "^1.1.7" +liftoff@~2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/liftoff/-/liftoff-2.5.0.tgz#2009291bb31cea861bbf10a7c15a28caf75c31ec" + integrity sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew= + dependencies: + extend "^3.0.0" + findup-sync "^2.0.0" + fined "^1.0.1" + flagged-respawn "^1.0.0" + is-plain-object "^2.0.4" + object.map "^1.0.0" + rechoir "^0.6.2" + resolve "^1.1.7" + linebreak@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/linebreak/-/linebreak-1.0.2.tgz#4b5781733e9a9eb2849dba2f963e47c887f8aa06" @@ -19189,7 +19190,7 @@ lodash.uniq@4.5.0, lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash@4.17.11, lodash@4.17.15, lodash@>4.17.4, lodash@^4, lodash@^4.0.0, lodash@^4.0.1, lodash@^4.10.0, lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0, lodash@~4.17.10, lodash@~4.17.15, lodash@~4.17.5: +lodash@4.17.11, lodash@4.17.15, lodash@>4.17.4, lodash@^4, lodash@^4.0.0, lodash@^4.0.1, lodash@^4.10.0, lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0, lodash@~4.17.10, lodash@~4.17.15, lodash@~4.17.19, lodash@~4.17.20: version "4.17.20" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== @@ -19937,7 +19938,7 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= -"minimatch@2 || 3", minimatch@3.0.4, minimatch@^3.0.2, minimatch@^3.0.4, minimatch@~3.0.2: +"minimatch@2 || 3", minimatch@3.0.4, minimatch@^3.0.2, minimatch@^3.0.4, minimatch@~3.0.2, minimatch@~3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== @@ -20072,7 +20073,7 @@ mkdirp@^0.3.5: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.5.tgz#de3e5f8961c88c787ee1368df849ac4413eca8d7" integrity sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc= -mkdirp@^1.0.3, mkdirp@^1.0.4: +mkdirp@^1.0.3, mkdirp@^1.0.4, mkdirp@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== @@ -21879,7 +21880,7 @@ path-exists@^4.0.0: resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== -path-is-absolute@^1.0.0, path-is-absolute@^1.0.1, path-is-absolute@~1.0.0: +path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= @@ -22404,10 +22405,10 @@ prettier@~2.0.5: resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.5.tgz#d6d56282455243f2f92cc1716692c08aa31522d4" integrity sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg== -pretty-bytes@^5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.3.0.tgz#f2849e27db79fb4d6cfe24764fc4134f165989f2" - integrity sha512-hjGrh+P926p4R4WbaB6OckyRtO0F0/lQBiT+0gnxjV+5kjPBrfVBFCsCLbMqVQeydvIoouYTCmmEURiH3R1Bdg== +pretty-bytes@^5.4.1: + version "5.4.1" + resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.4.1.tgz#cd89f79bbcef21e3d21eb0da68ffe93f803e884b" + integrity sha512-s1Iam6Gwz3JI5Hweaz4GoCD1WUNUIyzePFy5+Js2hjwGVt2Z79wNN+ZKOZ2vB6C+Xs6njyB84Z1IthQg8d9LxA== pretty-error@^2.1.1: version "2.1.1" @@ -24610,7 +24611,7 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= -resolve@1.1.7, resolve@~1.1.0, resolve@~1.1.7: +resolve@1.1.7, resolve@~1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= @@ -24715,7 +24716,7 @@ right-align@^0.1.1: dependencies: align-text "^0.1.1" -rimraf@2, rimraf@2.6.3, rimraf@^2.2.8, rimraf@^2.5.1, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3, rimraf@~2.6.2: +rimraf@2, rimraf@2.6.3, rimraf@^2.2.8, rimraf@^2.5.1, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== @@ -24736,7 +24737,7 @@ rimraf@^2.7.1: dependencies: glob "^7.1.3" -rimraf@^3.0.0, rimraf@^3.0.2: +rimraf@^3.0.0, rimraf@^3.0.2, rimraf@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== @@ -26551,6 +26552,13 @@ supports-color@^7.0.0, supports-color@^7.1.0: dependencies: has-flag "^4.0.0" +supports-color@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + supports-hyperlinks@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-1.0.1.tgz#71daedf36cc1060ac5100c351bb3da48c29c0ef7" @@ -27689,7 +27697,7 @@ undefsafe@^2.0.2: dependencies: debug "^2.2.0" -underscore.string@~3.3.4: +underscore.string@~3.3.5: version "3.3.5" resolved "https://registry.yarnpkg.com/underscore.string/-/underscore.string-3.3.5.tgz#fc2ad255b8bd309e239cbc5816fd23a9b7ea4023" integrity sha512-g+dpmgn+XBneLmXXo+sGlW5xQEt4ErkS3mgeN2GFbremYeMBSJKr9Wf2KJplQVaiPY/f7FN6atosWYNm9ovrYg== @@ -28377,7 +28385,7 @@ v8-to-istanbul@^6.0.1: convert-source-map "^1.6.0" source-map "^0.7.3" -v8flags@^3.0.1: +v8flags@^3.0.1, v8flags@~3.1.1: version "3.1.3" resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-3.1.3.tgz#fc9dc23521ca20c5433f81cc4eb9b3033bb105d8" integrity sha512-amh9CCg3ZxkzQ48Mhcb8iX7xpAfYJgePHxWMQCBWECpOSqJUXgY26ncA61UTV0BkPqfhcy6mzwCIoP4ygxpW8w==