diff --git a/docs/api/cases.asciidoc b/docs/api/cases.asciidoc index 00fbedc2d1299..45186a4e7d489 100644 --- a/docs/api/cases.asciidoc +++ b/docs/api/cases.asciidoc @@ -10,9 +10,9 @@ these APIs: * {security-guide}/cases-api-delete-all-comments.html[Delete all comments] * {security-guide}/cases-api-delete-comment.html[Delete comment] * {security-guide}/cases-api-find-alert.html[Find all alerts attached to a case] -* {security-guide}/cases-api-find-cases.html[Find cases] +* <> * {security-guide}/cases-api-find-cases-by-alert.html[Find cases by alert] -* {security-guide}/cases-api-find-connectors.html[Find connectors] +* <> * {security-guide}/cases-api-get-case-activity.html[Get all case activity] * {security-guide}/cases-api-get-all-case-comments.html[Get all case comments] * {security-guide}/cases-api-get-case.html[Get case] @@ -27,5 +27,10 @@ these APIs: * <> * {security-guide}/cases-api-update-comment.html[Update comment] +//CREATE include::cases/cases-api-create.asciidoc[leveloffset=+1] +//FIND +include::cases/cases-api-find-cases.asciidoc[leveloffset=+1] +include::cases/cases-api-find-connectors.asciidoc[leveloffset=+1] +//UPDATE include::cases/cases-api-update.asciidoc[leveloffset=+1] \ No newline at end of file diff --git a/docs/api/cases/cases-api-find-cases.asciidoc b/docs/api/cases/cases-api-find-cases.asciidoc new file mode 100644 index 0000000000000..334f45fee526d --- /dev/null +++ b/docs/api/cases/cases-api-find-cases.asciidoc @@ -0,0 +1,193 @@ +[[cases-api-find-cases]] +== Find cases API +++++ +Find cases +++++ + +Retrieves a paginated subset of cases. + +=== Request + +`GET :/api/cases/_find` + +`GET :/s//api/cases/_find` + +=== Prerequisite + +You must have `read` privileges for the *Cases* feature in the *Management*, +*{observability}*, or *Security* section of the +<>, depending on the +`owner` of the cases you're seeking. + +=== Path parameters + +``:: +(Optional, string) An identifier for the space. If it is not specified, the +default space is used. + +=== Query parameters + +`defaultSearchOperator`:: +(Optional, string) The default operator to use for the `simple_query_string`. +Defaults to `OR`. + +//// +`fields`:: +(Optional, array of strings) The fields in the entity to return in the response. +//// +`owner`:: +(Optional, string or array of strings) A filter to limit the retrieved cases to +a specific set of applications. Valid values are: `cases`, `observability`, +and `securitySolution`. If this parameter is omitted, the response contains all +cases that the user has access to read. + +`page`:: +(Optional, integer) The page number to return. Defaults to `1`. + +`perPage`:: +(Optional, integer) The number of rules to return per page. Defaults to `20`. + +`reporters`:: +(Optional, string or array of strings) Filters the returned cases by the +reporter's `username`. + +`search`:: +(Optional, string) An {es} +{ref}/query-dsl-simple-query-string-query.html[simple_query_string] query that +filters the objects in the response. + +`searchFields`:: +(Optional, string or array of strings) The fields to perform the +`simple_query_string` parsed query against. + +`sortField`:: +(Optional, string) Determines which field is used to sort the results, +`createdAt` or `updatedAt`. Defaults to `createdAt`. ++ +NOTE: Even though the JSON case object uses `created_at` and `updated_at` +fields, you must use `createdAt` and `updatedAt` fields in the URL +query. + +`sortOrder`:: +(Optional, string) Determines the sort order, which can be `desc` or `asc`. +Defaults to `desc`. + +`status`:: +(Optional, string) Filters the returned cases by state, which can be `open`, +`in-progress`, or `closed`. + +`tags`:: +(Optional, string or array of strings) Filters the returned cases by tags. + +=== Response code + +`200`:: + Indicates a successful call. + +=== Example + +Retrieve the first five cases with the `phishing` tag, in ascending order by +last update time: + +[source,sh] +-------------------------------------------------- +GET api/cases/_find?page=1&perPage=5&sortField=updatedAt&sortOrder=asc&tags=phishing +-------------------------------------------------- +// KIBANA + +The API returns a JSON object listing the retrieved cases. For example: + +[source,json] +-------------------------------------------------- +{ + "page": 1, + "per_page": 5, + "total": 2, + "cases": [ + { + "id": "abed3a70-71bd-11ea-a0b2-c51ea50a58e2", + "version": "WzExMCwxXQ==", + "comments": [], + "totalComment": 0, + "totalAlerts": 0, + "title": "The Long Game", + "tags": [ + "windows", + "phishing" + ], + "description": "Windows 95", + "settings": { + "syncAlerts": true + }, + "owner": "securitySolution", + "closed_at": null, + "closed_by": null, + "created_at": "2022-03-29T13:03:23.533Z", + "created_by": { + "email": "rhustler@email.com", + "full_name": "Rat Hustler", + "username": "rhustler" + }, + "status": "open", + "updated_at": null, + "updated_by": null, + "connector": { + "id": "131d4448-abe0-4789-939d-8ef60680b498", + "name": "My connector", + "type": ".jira", + "fields": { + "issueType": "10006", + "priority": null, + } + } + "external_service": null, + }, + { + "id": "a18b38a0-71b0-11ea-a0b2-c51ea50a58e2", + "version": "Wzk4LDFd", + "comments": [], + "totalComment": 0, + "totalAlerts": 0, + "title": "This case will self-destruct in 5 seconds", + "tags": [ + "phishing", + "social engineering", + "bubblegum" + ], + "description": "James Bond clicked on a highly suspicious email banner advertising cheap holidays for underpaid civil servants. Operation bubblegum is active. Repeat - operation bubblegum is now active!", + "settings": { + "syncAlerts": false + }, + "owner": "cases", + "closed_at": null, + "closed_by": null, + "created_at": "2022-03-29T11:30:02.658Z", + "created_by": { + "email": "ahunley@imf.usa.gov", + "full_name": "Alan Hunley", + "username": "ahunley" + }, + "status": "open", + "updated_at": "2022-03-29T12:01:50.244Z", + "updated_by": { + "full_name": "Classified", + "email": "classified@hms.oo.gov.uk", + "username": "M" + }, + "connector": { + "id": "131d4448-abe0-4789-939d-8ef60680b498", + "name": "My connector", + "type": ".resilient", + "fields": { + "issueTypes": [13], + "severityCode": 6, + } + }, + "external_service": null, + } + ], + "count_open_cases": 2, + "count_in_progress_cases":0, + "count_closed_cases": 0 +} +-------------------------------------------------- diff --git a/docs/api/cases/cases-api-find-connectors.asciidoc b/docs/api/cases/cases-api-find-connectors.asciidoc new file mode 100644 index 0000000000000..8643d569c980b --- /dev/null +++ b/docs/api/cases/cases-api-find-connectors.asciidoc @@ -0,0 +1,60 @@ +[[cases-api-find-connectors]] +== Find connectors API +++++ +Find connectors +++++ + +Retrieves information about <>. + +In particular, only the connectors that are supported for use in cases are +returned. Refer to the list of supported external incident management systems in +<>. + +=== Request + +`GET :/api/cases/configure/connectors/_find` + +`GET :/s//api/cases/configure/connectors/_find` + +=== Prerequisite + +You must have `read` privileges for the *Actions and Connectors* feature in the +*Management* section of the +<>. + +=== Path parameters + +``:: +(Optional, string) An identifier for the space. If it is not specified, the +default space is used. + +=== Response code + +`200`:: + Indicates a successful call. + +=== Example + +[source,sh] +-------------------------------------------------- +GET api/cases/configure/connectors/_find +-------------------------------------------------- +// KIBANA + +The API returns a JSON object describing the connectors and their settings: + +[source,json] +-------------------------------------------------- +[{ + "id":"61787f53-4eee-4741-8df6-8fe84fa616f7", + "actionTypeId": ".jira", + "name":"my-Jira", + "isMissingSecrets":false, + "config": { + "apiUrl":"https://elastic.atlassian.net/", + "projectKey":"ES" + }, + "isPreconfigured":false, + "referencedByCount":0 +}] +-------------------------------------------------- \ No newline at end of file diff --git a/docs/developer/advanced/images/sharing-saved-objects-dev-flowchart.png b/docs/developer/advanced/images/sharing-saved-objects-dev-flowchart.png deleted file mode 100644 index bc829059988db..0000000000000 Binary files a/docs/developer/advanced/images/sharing-saved-objects-dev-flowchart.png and /dev/null differ diff --git a/docs/developer/advanced/images/sharing-saved-objects-phase-1-dev-flowchart.png b/docs/developer/advanced/images/sharing-saved-objects-phase-1-dev-flowchart.png new file mode 100644 index 0000000000000..b1c14159ec01b Binary files /dev/null and b/docs/developer/advanced/images/sharing-saved-objects-phase-1-dev-flowchart.png differ diff --git a/docs/developer/advanced/images/sharing-saved-objects-phase-2-dev-flowchart.png b/docs/developer/advanced/images/sharing-saved-objects-phase-2-dev-flowchart.png new file mode 100644 index 0000000000000..44daa2e5b2fd4 Binary files /dev/null and b/docs/developer/advanced/images/sharing-saved-objects-phase-2-dev-flowchart.png differ diff --git a/docs/developer/advanced/images/sharing-saved-objects-step-6.png b/docs/developer/advanced/images/sharing-saved-objects-step-6.png new file mode 100644 index 0000000000000..b0fe40d926e27 Binary files /dev/null and b/docs/developer/advanced/images/sharing-saved-objects-step-6.png differ diff --git a/docs/developer/advanced/images/sharing-saved-objects-step-7.png b/docs/developer/advanced/images/sharing-saved-objects-step-7.png new file mode 100644 index 0000000000000..6e850d896543d Binary files /dev/null and b/docs/developer/advanced/images/sharing-saved-objects-step-7.png differ diff --git a/docs/developer/advanced/sharing-saved-objects.asciidoc b/docs/developer/advanced/sharing-saved-objects.asciidoc index 5dd93adf19123..59bab55724089 100644 --- a/docs/developer/advanced/sharing-saved-objects.asciidoc +++ b/docs/developer/advanced/sharing-saved-objects.asciidoc @@ -1,8 +1,8 @@ [[sharing-saved-objects]] -== Sharing Saved Objects +== Sharing saved objects -This guide describes the Sharing Saved Objects effort, and the breaking changes that plugin developers need to be aware of for the planned -8.0 release of {kib}. +This guide describes the "Sharing saved objects" effort, and the breaking changes that plugin developers need to be aware of for the planned +8.0 release of {kib}. It also describes how developers can take advantage of this feature. [[sharing-saved-objects-overview]] === Overview @@ -28,6 +28,12 @@ Ideally, most types of objects in {kib} will eventually be _shareable_; however, <> as a stepping stone for plugin developers to fully support this feature. +Implementing a shareable saved object type is done in two phases: + +- **Phase 1**: Convert an existing isolated object type into a share-capable one. Keep reading! +- **Phase 2**: Switch an existing share-capable object type into a shareable one, _or_ create a new shareable object type. Jump to the + <>! + [[sharing-saved-objects-breaking-changes]] === Breaking changes @@ -49,21 +55,21 @@ change the IDs of any existing objects that are not in the Default space. Changi TIP: External plugins can also convert their objects, but <>. -[[sharing-saved-objects-dev-flowchart]] -=== Developer Flowchart +[[sharing-saved-objects-phase-1]] +=== Phase 1 developer flowchart If you're still reading this page, you're probably developing a {kib} plugin that registers an object type, and you want to know what steps you need to take to prepare for the 8.0 release and mitigate any breaking changes! Depending on how you are using saved objects, you may need to take up to 5 steps, which are detailed in separate sections below. Refer to this flowchart: -image::images/sharing-saved-objects-dev-flowchart.png["Sharing Saved Objects developer flowchart"] +image::images/sharing-saved-objects-phase-1-dev-flowchart.png["Sharing Saved Objects phase 1 - developer flowchart"] TIP: There is a proof-of-concept (POC) pull request to demonstrate these changes. It first adds a simple test plugin that allows users to create and view notes. Then, it goes through the steps of the flowchart to convert the isolated "note" objects to become share-capable. As you read this guide, you can https://github.com/elastic/kibana/pull/107256[follow along in the POC] to see exactly how to take these steps. [[sharing-saved-objects-q1]] -=== Question 1 +==== Question 1 > *Do these objects contain links to other objects?* @@ -71,7 +77,7 @@ If your objects store _any_ links to other objects (with an object type/ID), you continue functioning after the 8.0 upgrade. [[sharing-saved-objects-step-1]] -=== Step 1 +==== Step 1 ⚠️ This step *must* be completed no later than the 7.16 release. ⚠️ @@ -117,7 +123,7 @@ migrations: { NOTE: Reminder, don't forget to add unit tests and integration tests! [[sharing-saved-objects-q2]] -=== Question 2 +==== Question 2 > *Are there any "deep links" to these objects?* @@ -130,7 +136,7 @@ Note that some URLs may contain <>! [[sharing-saved-objects-step-3]] -=== Step 3 +==== Step 3 ⚠️ This step will preferably be completed in the 7.16 release; it *must* be completed no later than the 8.0 release. ⚠️ @@ -206,7 +212,7 @@ TIP: See an example of this in https://github.com/elastic/kibana/pull/107256#use ] ``` -3. Update your Plugin class implementation to depend on the Core HTTP service and Spaces plugin API: +3. Update your Plugin class implementation to depend on the Spaces plugin API: + ```ts interface PluginStartDeps { @@ -218,11 +224,10 @@ export class MyPlugin implements Plugin<{}, {}, {}, PluginStartDeps> { core.application.register({ ... async mount(appMountParams: AppMountParameters) { - const [coreStart, pluginStartDeps] = await core.getStartServices(); - const { http } = coreStart; + const [, pluginStartDeps] = await core.getStartServices(); const { spaces: spacesApi } = pluginStartDeps; ... - // pass `http` and `spacesApi` to your app when you render it + // pass `spacesApi` to your app when you render it }, }); ... @@ -247,8 +252,8 @@ if (spacesApi && resolveResult.outcome === 'aliasMatch') { ``` <1> The `aliasPurpose` field is required as of 8.2, because the API response now includes the reason the alias was created to inform the client whether a toast should be shown or not. -<2> The `objectNoun` field is optional, it just changes "object" in the toast to whatever you specify -- you may want the toast to say - "dashboard" or "index pattern" instead! +<2> The `objectNoun` field is optional. It just changes "object" in the toast to whatever you specify -- you may want the toast to say + "dashboard" or "data view" instead. 5. And finally, in your deep link page, add a function that will create a callout in the case of a `'conflict'` outcome: + @@ -293,7 +298,7 @@ different outcomes.] NOTE: Reminder, don't forget to add unit tests and functional tests! [[sharing-saved-objects-step-4]] -=== Step 4 +==== Step 4 ⚠️ This step *must* be completed in the 8.0 release (no earlier and no later). ⚠️ @@ -315,7 +320,7 @@ TIP: See an example of this in https://github.com/elastic/kibana/pull/107256#use NOTE: Reminder, don't forget to add integration tests! [[sharing-saved-objects-q3]] -=== Question 3 +==== Question 3 > *Are these objects encrypted?* @@ -323,7 +328,7 @@ Saved objects can optionally be < object types are encrypted, so most plugin developers will not be affected. [[sharing-saved-objects-step-5]] -=== Step 5 +==== Step 5 ⚠️ This step *must* be completed in the 8.0 release (no earlier and no later). ⚠️ @@ -341,12 +346,141 @@ image::images/sharing-saved-objects-step-5.png["Sharing Saved Objects ESO migrat NOTE: Reminder, don't forget to add unit tests and integration tests! +[[sharing-saved-objects-phase-2]] +=== Phase 2 developer flowchart + +This section covers switching a share-capable object type into a shareable one _or_ creating a new shareable saved object type. Refer to +this flowchart: + +image::images/sharing-saved-objects-phase-2-dev-flowchart.png["Sharing Saved Objects phase 2 - developer flowchart"] + [[sharing-saved-objects-step-6]] -=== Step 6 +==== Step 6 + +> *Update your _server-side code_ to mark these objects as "shareable"* + +When you register your object, you need to set the proper `namespaceType`. If you have an existing object type that is "share-capable", you +can simply change it: + +image::images/sharing-saved-objects-step-6.png["Sharing Saved Objects registration (shareable)"] + +[[sharing-saved-objects-step-7]] +==== Step 7 + +> *Update saved object delete API usage to handle multiple spaces* + +If an object is shared to multiple spaces, it cannot be deleted without using the +https://github.com/elastic/kibana/blob/{branch}/docs/development/core/server/kibana-plugin-core-server.savedobjectsdeleteoptions.md[`force` +delete option]. You should always be aware when a saved object exists in multiple spaces, and you should warn users in that case. + +If your UI allows users to delete your objects, you can define a warning message like this: + +```tsx +const { namespaces, id } = savedObject; +const warningMessage = + namespaces.length > 1 || namespaces.includes('*') ? ( + + ) : null; +``` + +The <> in <> uses a +https://github.com/elastic/kibana/blob/{branch}/src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx[similar +approach] to show a warning in its delete confirmation modal: + +image::images/sharing-saved-objects-step-7.png["Sharing Saved Objects deletion warning"] + +[[sharing-saved-objects-step-8]] +==== Step 8 + +> *Allow users to view and change assigned spaces for your objects* + +Users will need a way to view what spaces your objects are currently assigned to and share them to additional spaces. You can accomplish +this in two ways, and many consumers will want to implement both: + +1. (Highly recommended) Add reusable components to your application, making it "space-aware". The space-related components are exported by + the spaces plugin, and you can use them in your own application. ++ +First, make sure your page contents are wrapped in a +https://github.com/elastic/kibana/blob/{branch}/x-pack/plugins/spaces/public/spaces_context/types.ts[spaces context provider]: ++ +```tsx +const ContextWrapper = useMemo( + () => + spacesApi ? spacesApi.ui.components.getSpacesContextProvider : getEmptyFunctionComponent, + [spacesApi] +); -> *Update your code to make your objects shareable* +... -_This is not required for the 8.0 release; this additional information will be added in the near future!_ +return ( + + + +); +``` ++ +Second, display a https://github.com/elastic/kibana/blob/{branch}/x-pack/plugins/spaces/public/space_list/types.ts[list of spaces] for an +object, and third, show a +https://github.com/elastic/kibana/blob/{branch}/x-pack/plugins/spaces/public/share_saved_objects_to_space/types.ts[flyout] for the user to +edit the object's assigned spaces. You may want to follow the example of the <> and +https://github.com/elastic/kibana/blob/{branch}/src/plugins/data_view_management/public/components/index_pattern_table/spaces_list.tsx[combine +these into a single component] so that the space list can be clicked to show the flyout: ++ +```tsx +const [showFlyout, setShowFlyout] = useState(false); +const LazySpaceList = useCallback(spacesApi.ui.components.getSpaceList, [spacesApi]); +const LazyShareToSpaceFlyout = useCallback(spacesApi.ui.components.getShareToSpaceFlyout, [spacesApi]); + +const shareToSpaceFlyoutProps: ShareToSpaceFlyoutProps = { + savedObjectTarget: { + type: myObject.type, + namespaces: myObject.namespaces, + id: myObject.id, + icon: 'beaker', <1> + title: myObject.attributes.title, <2> + noun: OBJECT_NOUN, <3> + }, + onUpdate: () => { /* callback when the object is updated */ }, + onClose: () => setShowFlyout(false), +}; + +return ( + <> + + listOnClick={() => setShowFlyout(true)} + /> + {showFlyout && } + +); +``` +<1> The `icon` field is optional. It specifies an https://elastic.github.io/eui/#/display/icons[EUI icon] type that will be displayed in the + flyout header. +<2> The `title` field is optional. It specifies a human-readable identifier for your object that will be displayed in the flyout header. +<3> The `noun` field is optional. It just changes "object" in the flyout to whatever you specify -- you may want the flyout to say + "dashboard" or "data view" instead. +<4> The `behaviorContext` field is optional. It controls how the space list is displayed. When using an `"outside-space"` behavior context, + the space list is rendered outside of any particular space, so the active space is included in the list. On the other hand, when using a + `"within-space"` behavior context, the space list is rendered within the active space, so the active space is excluded from the list. + +2. Allow users to access your objects in the <> in <>. You can do this by + ensuring that your objects are marked as + https://github.com/elastic/kibana/blob/{branch}/docs/development/core/server/kibana-plugin-core-server.savedobjectstypemanagementdefinition.md[importable and exportable] in your <>: ++ +```ts +name: 'my-object-type', +management: { + isImportableAndExportable: true, +}, +... +``` +If you do this, then your objects will be visible in the <>, where users can assign +them to multiple spaces. [[sharing-saved-objects-faq]] === Frequently asked questions (FAQ) diff --git a/docs/developer/architecture/core/saved-objects-service.asciidoc b/docs/developer/architecture/core/saved-objects-service.asciidoc index 54a5c319c6222..cc669be8ec9fa 100644 --- a/docs/developer/architecture/core/saved-objects-service.asciidoc +++ b/docs/developer/architecture/core/saved-objects-service.asciidoc @@ -32,6 +32,7 @@ wanting to use Saved Objects. === Server side usage +[[saved-objects-type-registration]] ==== Registering a Saved Object type Saved object type definitions should be defined in their own `my_plugin/server/saved_objects` directory. diff --git a/packages/kbn-analytics/BUILD.bazel b/packages/kbn-analytics/BUILD.bazel index d144ab186a6a1..e2cc4b1f58f24 100644 --- a/packages/kbn-analytics/BUILD.bazel +++ b/packages/kbn-analytics/BUILD.bazel @@ -23,11 +23,13 @@ NPM_MODULE_EXTRA_FILES = [ ] RUNTIME_DEPS = [ + "@npm//moment", "@npm//moment-timezone", "@npm//tslib", ] TYPES_DEPS = [ + "@npm//moment", "@npm//@types/moment-timezone", "@npm//@types/node", ] @@ -70,6 +72,7 @@ ts_project( srcs = SRCS, deps = TYPES_DEPS, declaration = True, + declaration_map = True, emit_declaration_only = True, out_dir = "target_types", root_dir = "src", diff --git a/packages/kbn-analytics/tsconfig.json b/packages/kbn-analytics/tsconfig.json index de4301e2a2ac0..afdacfb1d1ae8 100644 --- a/packages/kbn-analytics/tsconfig.json +++ b/packages/kbn-analytics/tsconfig.json @@ -2,6 +2,7 @@ "extends": "../../tsconfig.bazel.json", "compilerOptions": { "declaration": true, + "declarationMap": true, "emitDeclarationOnly": true, "isolatedModules": true, "outDir": "./target_types", diff --git a/packages/kbn-apm-config-loader/BUILD.bazel b/packages/kbn-apm-config-loader/BUILD.bazel index bcdbefb132aa6..e5542391a3c37 100644 --- a/packages/kbn-apm-config-loader/BUILD.bazel +++ b/packages/kbn-apm-config-loader/BUILD.bazel @@ -65,6 +65,7 @@ ts_project( srcs = SRCS, deps = TYPES_DEPS, declaration = True, + declaration_map = True, emit_declaration_only = True, out_dir = "target_types", root_dir = "src", diff --git a/packages/kbn-apm-config-loader/tsconfig.json b/packages/kbn-apm-config-loader/tsconfig.json index 7d2597d318b31..35e9c12eb90ea 100644 --- a/packages/kbn-apm-config-loader/tsconfig.json +++ b/packages/kbn-apm-config-loader/tsconfig.json @@ -2,6 +2,7 @@ "extends": "../../tsconfig.bazel.json", "compilerOptions": { "declaration": true, + "declarationMap": true, "emitDeclarationOnly": true, "outDir": "./target_types", "rootDir": "./src", diff --git a/packages/kbn-apm-utils/BUILD.bazel b/packages/kbn-apm-utils/BUILD.bazel index 9ca9009bb7186..a2505e0556b9b 100644 --- a/packages/kbn-apm-utils/BUILD.bazel +++ b/packages/kbn-apm-utils/BUILD.bazel @@ -50,6 +50,7 @@ ts_project( srcs = SRCS, deps = TYPES_DEPS, declaration = True, + declaration_map = True, emit_declaration_only = True, out_dir = "target_types", root_dir = "src", diff --git a/packages/kbn-apm-utils/tsconfig.json b/packages/kbn-apm-utils/tsconfig.json index 9c8c443436ce5..f4c8a0de0e603 100644 --- a/packages/kbn-apm-utils/tsconfig.json +++ b/packages/kbn-apm-utils/tsconfig.json @@ -2,6 +2,7 @@ "extends": "../../tsconfig.bazel.json", "compilerOptions": { "declaration": true, + "declarationMap": true, "emitDeclarationOnly": true, "outDir": "target_types", "rootDir": "src", diff --git a/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts b/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts index cf1afbb810c71..17c3af046f92f 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts +++ b/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts @@ -114,6 +114,7 @@ export const schema = Joi.object() try: Joi.number().default(120000), waitFor: Joi.number().default(20000), esRequestTimeout: Joi.number().default(30000), + kibanaReportCompletion: Joi.number().default(60_000), kibanaStabilize: Joi.number().default(15000), navigateStatusPageCheck: Joi.number().default(250), @@ -166,7 +167,9 @@ export const schema = Joi.object() mochaReporter: Joi.object() .keys({ - captureLogOutput: Joi.boolean().default(!!process.env.CI), + captureLogOutput: Joi.boolean().default( + !!process.env.CI && !process.env.DISABLE_CI_LOG_OUTPUT_CAPTURE + ), sendToCiStats: Joi.boolean().default(!!process.env.CI), }) .default(), diff --git a/packages/kbn-type-summarizer/src/lib/bazel_cli_config.ts b/packages/kbn-type-summarizer/src/lib/bazel_cli_config.ts index 160e33174d9f7..6f02160a1cb3f 100644 --- a/packages/kbn-type-summarizer/src/lib/bazel_cli_config.ts +++ b/packages/kbn-type-summarizer/src/lib/bazel_cli_config.ts @@ -19,6 +19,9 @@ const TYPE_SUMMARIZER_PACKAGES = [ '@kbn/mapbox-gl', '@kbn/ace', '@kbn/alerts', + '@kbn/analytics', + '@kbn/apm-config-loader', + '@kbn/apm-utils', ]; type TypeSummarizerType = 'api-extractor' | 'type-summarizer'; diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/threat_intel_panel_view.tsx b/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/threat_intel_panel_view.tsx index 0f80185750261..2709c193caffd 100644 --- a/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/threat_intel_panel_view.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/threat_intel_panel_view.tsx @@ -25,7 +25,7 @@ const columns: Array> = [ render: shortenCountIntoString, sortable: true, truncateText: true, - width: '20%', + width: '70px', align: 'right', }, { diff --git a/x-pack/test/accessibility/apps/spaces.ts b/x-pack/test/accessibility/apps/spaces.ts index 78e5dd1f2f2c3..567f958f5f8a4 100644 --- a/x-pack/test/accessibility/apps/spaces.ts +++ b/x-pack/test/accessibility/apps/spaces.ts @@ -18,8 +18,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const retry = getService('retry'); const toasts = getService('toasts'); - // FLAKY: https://github.com/elastic/kibana/issues/100968 - describe.skip('Kibana spaces page meets a11y validations', () => { + describe('Kibana spaces page meets a11y validations', () => { before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/empty_kibana'); await PageObjects.common.navigateToApp('home'); @@ -98,7 +97,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { // test starts with deleting space b so we can get the space selection page instead of logging out in the test it('a11y test for space selection page', async () => { await PageObjects.spaceSelector.confirmDeletingSpace(); - await a11y.testAppSnapshot(); + await retry.try(async () => { + await a11y.testAppSnapshot(); + }); await PageObjects.spaceSelector.clickSpaceCard('default'); }); }); diff --git a/x-pack/test/upgrade/apps/reporting/reporting_smoke_tests.ts b/x-pack/test/upgrade/apps/reporting/reporting_smoke_tests.ts index e7769f2761f3f..14136b23abfd5 100644 --- a/x-pack/test/upgrade/apps/reporting/reporting_smoke_tests.ts +++ b/x-pack/test/upgrade/apps/reporting/reporting_smoke_tests.ts @@ -89,11 +89,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const postUrl = await find.byXPath(`//button[descendant::*[text()='Copy POST URL']]`); await postUrl.click(); const url = await browser.getClipboardValue(); - await reportingAPI.expectAllJobsToFinishSuccessfully( - await Promise.all([ - reportingAPI.postJob(parse(url).pathname + '?' + parse(url).query), - ]) - ); + await reportingAPI.expectAllJobsToFinishSuccessfully([ + await reportingAPI.postJob(parse(url).pathname + '?' + parse(url).query), + ]); usage = (await usageAPI.getUsageStats()) as UsageStats; reportingAPI.expectCompletedReportCount(usage, completedReportCount + 1); }); diff --git a/x-pack/test/upgrade/reporting_services.ts b/x-pack/test/upgrade/reporting_services.ts index 13186cb9b2a75..2de3b72bc9a47 100644 --- a/x-pack/test/upgrade/reporting_services.ts +++ b/x-pack/test/upgrade/reporting_services.ts @@ -47,33 +47,34 @@ export function ReportingAPIProvider({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esSupertest = getService('esSupertest'); const retry = getService('retry'); + const config = getService('config'); return { - async waitForJobToFinish(downloadReportPath: string) { - log.debug(`Waiting for job to finish: ${downloadReportPath}`); - const JOB_IS_PENDING_CODE = 503; - - const statusCode = await new Promise((resolve) => { - const intervalId = setInterval(async () => { - const response = (await supertest + async waitForJobToFinish(downloadReportPath: string, options?: { timeout?: number }) { + await retry.waitForWithTimeout( + `job ${downloadReportPath} finished`, + options?.timeout ?? config.get('timeouts.kibanaReportCompletion'), + async () => { + const response = await supertest .get(downloadReportPath) .responseType('blob') - .set('kbn-xsrf', 'xxx')) as any; - if (response.statusCode === 503) { + .set('kbn-xsrf', 'xxx'); + + if (response.status === 503) { log.debug(`Report at path ${downloadReportPath} is pending`); - } else if (response.statusCode === 200) { - log.debug(`Report at path ${downloadReportPath} is complete`); - } else { - log.debug(`Report at path ${downloadReportPath} returned code ${response.statusCode}`); + return false; } - if (response.statusCode !== JOB_IS_PENDING_CODE) { - clearInterval(intervalId); - resolve(response.statusCode); + + log.debug(`Report at path ${downloadReportPath} returned code ${response.status}`); + + if (response.status === 200) { + log.debug(`Report at path ${downloadReportPath} is complete`); + return true; } - }, 1500); - }); - expect(statusCode).to.be(200); + throw new Error(`unexpected status code ${response.status}`); + } + ); }, async expectAllJobsToFinishSuccessfully(jobPaths: string[]) {