diff --git a/.buildkite/scripts/steps/checks/bazel_packages.sh b/.buildkite/scripts/steps/checks/bazel_packages.sh index ca82c6fef609e1..a8a631ed48ae45 100755 --- a/.buildkite/scripts/steps/checks/bazel_packages.sh +++ b/.buildkite/scripts/steps/checks/bazel_packages.sh @@ -6,5 +6,12 @@ source .buildkite/scripts/common/util.sh echo --- Check Bazel Packages Manifest node scripts/generate packages_build_manifest - check_for_changed_files 'node scripts/generate packages_build_manifest' true + +echo --- Check Codeowners Manifest +if [ -f ".github/CODEOWNERS" ]; then + node scripts/generate codeowners + check_for_changed_files 'node scripts/generate codeowners' true +else + echo "skipping, no existing .github/CODEOWNERS file found" +fi diff --git a/.eslintrc.js b/.eslintrc.js index b73b88ba95de9c..406e58e17d7a6e 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -9,7 +9,9 @@ const Path = require('path'); const Fs = require('fs'); -const globby = require('globby'); +const normalizePath = require('normalize-path'); +const { discoverPackageManifestPaths, Jsonc } = require('@kbn/bazel-packages'); +const { REPO_ROOT } = require('@kbn/utils'); const APACHE_2_0_LICENSE_HEADER = ` /* @@ -119,15 +121,10 @@ const VENN_DIAGRAM_HEADER = ` */ `; -const packagePkgJsons = globby.sync('*/package.json', { - cwd: Path.resolve(__dirname, 'packages'), - absolute: true, -}); - /** Packages which should not be included within production code. */ -const DEV_PACKAGES = packagePkgJsons.flatMap((path) => { - const pkg = JSON.parse(Fs.readFileSync(path, 'utf8')); - return pkg.kibana && pkg.kibana.devOnly ? Path.dirname(Path.basename(path)) : []; +const DEV_PACKAGE_DIRS = discoverPackageManifestPaths(REPO_ROOT).flatMap((path) => { + const manifest = Jsonc.parse(Fs.readFileSync(path, 'utf8')); + return !!manifest.devOnly ? normalizePath(Path.relative(REPO_ROOT, Path.dirname(path))) : []; }); /** Directories (at any depth) which include dev-only code. */ @@ -145,6 +142,7 @@ const DEV_DIRECTORIES = [ 'integration_tests', 'manual_tests', 'mock', + 'mocks', 'storybook', 'scripts', 'test', @@ -153,6 +151,7 @@ const DEV_DIRECTORIES = [ 'test_utilities', 'test_helpers', 'tests_client_integration', + 'tsd_tests', ]; /** File patterns for dev-only code. */ @@ -171,7 +170,7 @@ const DEV_FILE_PATTERNS = [ /** Glob patterns which describe dev-only code. */ const DEV_PATTERNS = [ - ...DEV_PACKAGES.map((pkg) => `packages/${pkg}/**/*`), + ...DEV_PACKAGE_DIRS.map((pkg) => `${pkg}/**/*`), ...DEV_DIRECTORIES.map((dir) => `{packages,src,x-pack}/**/${dir}/**/*`), ...DEV_FILE_PATTERNS.map((file) => `{packages,src,x-pack}/**/${file}`), 'packages/kbn-interpreter/tasks/**/*', diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 71af2a3e67230f..9d53eb77959438 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -42,7 +42,6 @@ /src/plugins/chart_expressions/expression_partition_vis/ @elastic/kibana-vis-editors /src/plugins/chart_expressions/expression_xy/ @elastic/kibana-vis-editors /src/plugins/url_forwarding/ @elastic/kibana-vis-editors -/packages/kbn-tinymath/ @elastic/kibana-vis-editors /x-pack/test/functional/apps/lens @elastic/kibana-vis-editors /x-pack/test/api_integration/apis/lens/ @elastic/kibana-vis-editors /test/functional/apps/visualize/ @elastic/kibana-vis-editors @@ -62,12 +61,6 @@ /examples/field_formats_example/ @elastic/kibana-app-services /examples/partial_results_example/ @elastic/kibana-app-services /examples/search_examples/ @elastic/kibana-app-services -/packages/kbn-datemath/ @elastic/kibana-app-services -/packages/kbn-interpreter/ @elastic/kibana-app-services -/packages/kbn-monaco/ @elastic/kibana-app-services -/packages/kbn-react-field/ @elastic/kibana-app-services -/packages/kbn-es-query/ @elastic/kibana-app-services -/packages/kbn-field-types/ @elastic/kibana-app-services /src/plugins/bfetch/ @elastic/kibana-app-services /src/plugins/data/ @elastic/kibana-app-services /src/plugins/data_views/ @elastic/kibana-app-services @@ -139,12 +132,9 @@ x-pack/examples/files_example @elastic/kibana-app-services /x-pack/plugins/apm/ @elastic/apm-ui /x-pack/test/functional/apps/apm/ @elastic/apm-ui /x-pack/test/apm_api_integration/ @elastic/apm-ui -/src/plugins/apm_oss/ @elastic/apm-ui /src/apm.js @elastic/kibana-core @vigneshshanmugam -/packages/kbn-apm-config-loader/ @elastic/kibana-core @vigneshshanmugam +/packages/kbn-apm-config-loader/ @vigneshshanmugam /src/core/types/elasticsearch @elastic/apm-ui -/packages/kbn-apm-synthtrace/ @elastic/apm-ui -/packages/kbn-shared-svg @elastic/apm-ui /packages/kbn-utility-types/src/dot.ts @dgieselaar /packages/kbn-utility-types/src/dot_test.ts @dgieselaar #CC# /src/plugins/apm_oss/ @elastic/apm-ui @@ -220,7 +210,6 @@ x-pack/examples/files_example @elastic/kibana-app-services /x-pack/test/functional/apps/transform/ @elastic/ml-ui /x-pack/test/functional/services/transform/ @elastic/ml-ui /x-pack/test/functional_basic/apps/transform/ @elastic/ml-ui -/x-pack/packages/ml/ @elastic/ml-ui /examples/response_stream/ @elastic/ml-ui # Maps @@ -234,39 +223,11 @@ x-pack/examples/files_example @elastic/kibana-app-services /x-pack/plugins/stack_alerts/public/alert_types/geo_containment @elastic/kibana-gis #CC# /x-pack/plugins/file_upload @elastic/kibana-gis /x-pack/plugins/file_upload @elastic/kibana-gis -/packages/kbn-mapbox-gl @elastic/kibana-gis # Operations /src/dev/license_checker/config.ts @elastic/kibana-operations -/packages/kbn-docs-utils/ @elastic/kibana-operations /src/dev/ @elastic/kibana-operations /src/setup_node_env/ @elastic/kibana-operations -/packages/*eslint*/ @elastic/kibana-operations -/packages/*babel*/ @elastic/kibana-operations -/packages/kbn-ambient-ui-types/ @elastic/kibana-operations -/packages/kbn-ambient-storybook-types/ @elastic/kibana-operations -/packages/kbn-bazel-packages/ @elastic/kibana-operations -/packages/kbn-bazel-runner/ @elastic/kibana-operations -/packages/kbn-cli-dev-mode/ @elastic/kibana-operations -/packages/kbn-dev-utils*/ @elastic/kibana-operations -/packages/kbn-es-archiver/ @elastic/kibana-operations -/packages/kbn-es/ @elastic/kibana-operations -/packages/kbn-eslint-plugin-imports/ @elastic/kibana-operations -/packages/kbn-generate/ @elastic/kibana-operations -/packages/kbn-import-resolver/ @elastic/kibana-operations -/packages/kbn-optimizer/ @elastic/kibana-operations -/packages/kbn-plugin-discovery/ @elastic/kibana-operations -/packages/kbn-pm/ @elastic/kibana-operations -/packages/kbn-test/ @elastic/kibana-operations -/packages/kbn-type-summarizer*/ @elastic/kibana-operations -/packages/kbn-ui-shared-deps-npm/ @elastic/kibana-operations -/packages/kbn-ui-shared-deps-src/ @elastic/kibana-operations -/packages/kbn-utils/ @elastic/kibana-operations -/packages/kbn-jsonc/ @elastic/kibana-operations -/packages/kbn-kibana-manifest-parser/ @elastic/kibana-operations -/packages/kbn-kibana-manifest-schema/ @elastic/kibana-operations -/packages/kbn-managed-vscode-config/ @elastic/kibana-operations -/packages/kbn-managed-vscode-config-cli/ @elastic/kibana-operations /src/cli/keystore/ @elastic/kibana-operations /.ci/es-snapshots/ @elastic/kibana-operations /.github/workflows/ @elastic/kibana-operations @@ -277,12 +238,8 @@ x-pack/examples/files_example @elastic/kibana-app-services /.bazelrc.common @elastic/kibana-operations /.bazelversion @elastic/kibana-operations /WORKSPACE.bazel @elastic/kibana-operations -#CC# /packages/kbn-expect/ @elastic/kibana-operations /.buildkite/ @elastic/kibana-operations -# Performance testing -/packages/kbn-performance-testing-dataset-extractor/ @elastic/kibana-performance-testing - # Quality Assurance /src/dev/code_coverage @elastic/kibana-qa /vars/*Coverage.groovy @elastic/kibana-qa @@ -307,15 +264,6 @@ x-pack/examples/files_example @elastic/kibana-app-services /x-pack/plugins/saved_objects_tagging/ @elastic/kibana-core /x-pack/test/saved_objects_field_count/ @elastic/kibana-core /x-pack/test/saved_object_tagging/ @elastic/kibana-core -/packages/core/ @elastic/kibana-core -/packages/analytics/ @elastic/kibana-core -/packages/kbn-config-schema/ @elastic/kibana-core -/packages/kbn-std/ @elastic/kibana-core -/packages/kbn-config/ @elastic/kibana-core -/packages/kbn-logging/ @elastic/kibana-core -/packages/kbn-logging-mocks/ @elastic/kibana-core -/packages/kbn-server-http-tools/ @elastic/kibana-core -/packages/kbn-es-errors/ @elastic/kibana-core /src/plugins/saved_objects_management/ @elastic/kibana-core /src/plugins/advanced_settings/ @elastic/kibana-core /x-pack/plugins/global_search_bar/ @elastic/kibana-core @@ -328,12 +276,7 @@ x-pack/examples/files_example @elastic/kibana-app-services #CC# /src/plugins/newsfeed @elastic/kibana-core #CC# /x-pack/plugins/global_search_providers/ @elastic/kibana-core -# Kibana Docs -/packages/kbn-doc-links/ @elastic/kibana-docs - # Kibana Telemetry -/packages/kbn-analytics/ @elastic/kibana-core -/packages/kbn-telemetry-tools/ @elastic/kibana-core /src/plugins/kibana_usage_collection/ @elastic/kibana-core /src/plugins/newsfeed/ @elastic/kibana-core /src/plugins/telemetry/ @elastic/kibana-core @@ -349,14 +292,9 @@ x-pack/examples/files_example @elastic/kibana-app-services # Kibana Localization /src/dev/i18n/ @elastic/kibana-localization @elastic/kibana-core /src/core/public/i18n/ @elastic/kibana-localization @elastic/kibana-core -/packages/kbn-i18n/ @elastic/kibana-localization @elastic/kibana-core #CC# /x-pack/plugins/translations/ @elastic/kibana-localization @elastic/kibana-core # Kibana Platform Security -/packages/kbn-crypto/ @elastic/kibana-security -/packages/kbn-handlebars/ @elastic/kibana-security -/packages/kbn-user-profile-components/ @elastic/kibana-security -/packages/core/http/core-http-server-internal/src/csp/ @elastic/kibana-security @elastic/kibana-core /src/plugins/interactive_setup/ @elastic/kibana-security /src/plugins/telemetry/server/config/telemetry_labels.ts @elastic/kibana-security /test/interactive_setup_api_integration/ @elastic/kibana-security @@ -421,7 +359,6 @@ x-pack/examples/files_example @elastic/kibana-app-services /x-pack/plugins/upgrade_assistant/ @elastic/platform-deployment-management /x-pack/plugins/watcher/ @elastic/platform-deployment-management /x-pack/plugins/ingest_pipelines/ @elastic/platform-deployment-management -/packages/kbn-ace/ @elastic/platform-deployment-management #CC# /x-pack/plugins/cross_cluster_replication/ @elastic/platform-deployment-management # Security Solution @@ -559,7 +496,6 @@ x-pack/examples/files_example @elastic/kibana-app-services /x-pack/plugins/security_solution/public/common/components/sourcerer @elastic/security-solution-platform /x-pack/plugins/security_solution/server/lib/sourcerer @elastic/security-solution-platform -/packages/kbn-securitysolution* @elastic/security-solution-platform ## Security Threat Intelligence - Under Security Platform /x-pack/plugins/security_solution/public/common/components/threat_match @elastic/security-solution-platform @@ -637,7 +573,6 @@ x-pack/test/threat_intelligence_cypress @elastic/protections-experience # Design (at the bottom for specificity of SASS files) **/*.scss @elastic/kibana-design -#CC# /packages/kbn-ui-framework/ @elastic/kibana-design # Observability design /x-pack/plugins/apm/**/*.scss @elastic/observability-design @@ -680,16 +615,11 @@ x-pack/test/threat_intelligence_cypress @elastic/protections-experience # Application Experience -## Shared UX Team -/packages/shared-ux/ @elastic/shared-ux -/packages/shared-ux-*/ @elastic/shared-ux - ### Kibana React (to be deprecated) /src/plugins/kibana_react/ @elastic/shared-ux /src/plugins/kibana_react/public/code_editor @elastic/shared-ux @elastic/kibana-presentation ### Home Plugin and Packages -/packages/home/ @elastic/shared-ux /src/plugins/home/public @elastic/shared-ux /src/plugins/home/server/*.ts @elastic/shared-ux /src/plugins/home/server/services/ @elastic/shared-ux @@ -704,3 +634,311 @@ x-pack/test/threat_intelligence_cypress @elastic/protections-experience #CC# /src/plugins/home/public @elastic/shared-ux #CC# /src/plugins/home/server/services/ @elastic/shared-ux #CC# /src/plugins/home/ @elastic/shared-ux + +#### +## Everything below this comment is automatically generated based on kibana.jsonc +## "owner" fields. This file is automatically updated by CI or can be updated locally +## by running `node scripts/generate codeowners`. +#### + +packages/analytics/client @elastic/kibana-core +packages/analytics/shippers/elastic_v3/browser @elastic/kibana-core +packages/analytics/shippers/elastic_v3/common @elastic/kibana-core +packages/analytics/shippers/elastic_v3/server @elastic/kibana-core +packages/analytics/shippers/fullstory @elastic/kibana-core +packages/core/analytics/core-analytics-browser @elastic/kibana-core +packages/core/analytics/core-analytics-browser-internal @elastic/kibana-core +packages/core/analytics/core-analytics-browser-mocks @elastic/kibana-core +packages/core/analytics/core-analytics-server @elastic/kibana-core +packages/core/analytics/core-analytics-server-internal @elastic/kibana-core +packages/core/analytics/core-analytics-server-mocks @elastic/kibana-core +packages/core/application/core-application-browser @elastic/kibana-core +packages/core/application/core-application-browser-internal @elastic/kibana-core +packages/core/application/core-application-browser-mocks @elastic/kibana-core +packages/core/application/core-application-common @elastic/kibana-core +packages/core/base/core-base-browser-internal @elastic/kibana-core +packages/core/base/core-base-browser-mocks @elastic/kibana-core +packages/core/base/core-base-common @elastic/kibana-core +packages/core/base/core-base-common-internal @elastic/kibana-core +packages/core/base/core-base-server-internal @elastic/kibana-core +packages/core/base/core-base-server-mocks @elastic/kibana-core +packages/core/capabilities/core-capabilities-browser-internal @elastic/kibana-core +packages/core/capabilities/core-capabilities-browser-mocks @elastic/kibana-core +packages/core/capabilities/core-capabilities-common @elastic/kibana-core +packages/core/capabilities/core-capabilities-server @elastic/kibana-core +packages/core/capabilities/core-capabilities-server-internal @elastic/kibana-core +packages/core/capabilities/core-capabilities-server-mocks @elastic/kibana-core +packages/core/chrome/core-chrome-browser @elastic/kibana-core +packages/core/chrome/core-chrome-browser-internal @elastic/kibana-core +packages/core/chrome/core-chrome-browser-mocks @elastic/kibana-core +packages/core/config/core-config-server-internal @elastic/kibana-core +packages/core/deprecations/core-deprecations-browser @elastic/kibana-core +packages/core/deprecations/core-deprecations-browser-internal @elastic/kibana-core +packages/core/deprecations/core-deprecations-browser-mocks @elastic/kibana-core +packages/core/deprecations/core-deprecations-common @elastic/kibana-core +packages/core/deprecations/core-deprecations-server @elastic/kibana-core +packages/core/deprecations/core-deprecations-server-internal @elastic/kibana-core +packages/core/deprecations/core-deprecations-server-mocks @elastic/kibana-core +packages/core/doc-links/core-doc-links-browser @elastic/kibana-core +packages/core/doc-links/core-doc-links-browser-internal @elastic/kibana-core +packages/core/doc-links/core-doc-links-browser-mocks @elastic/kibana-core +packages/core/doc-links/core-doc-links-server @elastic/kibana-core +packages/core/doc-links/core-doc-links-server-internal @elastic/kibana-core +packages/core/doc-links/core-doc-links-server-mocks @elastic/kibana-core +packages/core/elasticsearch/core-elasticsearch-client-server-internal @elastic/kibana-core +packages/core/elasticsearch/core-elasticsearch-client-server-mocks @elastic/kibana-core +packages/core/elasticsearch/core-elasticsearch-server @elastic/kibana-core +packages/core/elasticsearch/core-elasticsearch-server-internal @elastic/kibana-core +packages/core/elasticsearch/core-elasticsearch-server-mocks @elastic/kibana-core +packages/core/environment/core-environment-server-internal @elastic/kibana-core +packages/core/environment/core-environment-server-mocks @elastic/kibana-core +packages/core/execution-context/core-execution-context-browser @elastic/kibana-core +packages/core/execution-context/core-execution-context-browser-internal @elastic/kibana-core +packages/core/execution-context/core-execution-context-browser-mocks @elastic/kibana-core +packages/core/execution-context/core-execution-context-common @elastic/kibana-core +packages/core/execution-context/core-execution-context-server @elastic/kibana-core +packages/core/execution-context/core-execution-context-server-internal @elastic/kibana-core +packages/core/execution-context/core-execution-context-server-mocks @elastic/kibana-core +packages/core/fatal-errors/core-fatal-errors-browser @elastic/kibana-core +packages/core/fatal-errors/core-fatal-errors-browser-internal @elastic/kibana-core +packages/core/fatal-errors/core-fatal-errors-browser-mocks @elastic/kibana-core +packages/core/http/core-http-browser @elastic/kibana-core +packages/core/http/core-http-browser-internal @elastic/kibana-core +packages/core/http/core-http-browser-mocks @elastic/kibana-core +packages/core/http/core-http-common @elastic/kibana-core +packages/core/http/core-http-context-server-internal @elastic/kibana-core +packages/core/http/core-http-context-server-mocks @elastic/kibana-core +packages/core/http/core-http-router-server-internal @elastic/kibana-core +packages/core/http/core-http-router-server-mocks @elastic/kibana-core +packages/core/http/core-http-server @elastic/kibana-core +packages/core/http/core-http-server-internal @elastic/kibana-core +packages/core/http/core-http-server-mocks @elastic/kibana-core +packages/core/i18n/core-i18n-browser @elastic/kibana-core +packages/core/i18n/core-i18n-browser-internal @elastic/kibana-core +packages/core/i18n/core-i18n-browser-mocks @elastic/kibana-core +packages/core/i18n/core-i18n-server @elastic/kibana-core +packages/core/i18n/core-i18n-server-internal @elastic/kibana-core +packages/core/i18n/core-i18n-server-mocks @elastic/kibana-core +packages/core/injected-metadata/core-injected-metadata-browser @elastic/kibana-core +packages/core/injected-metadata/core-injected-metadata-browser-internal @elastic/kibana-core +packages/core/injected-metadata/core-injected-metadata-browser-mocks @elastic/kibana-core +packages/core/injected-metadata/core-injected-metadata-common-internal @elastic/kibana-core +packages/core/integrations/core-integrations-browser-internal @elastic/kibana-core +packages/core/integrations/core-integrations-browser-mocks @elastic/kibana-core +packages/core/logging/core-logging-server @elastic/kibana-core +packages/core/logging/core-logging-server-internal @elastic/kibana-core +packages/core/logging/core-logging-server-mocks @elastic/kibana-core +packages/core/metrics/core-metrics-collectors-server-internal @elastic/kibana-core +packages/core/metrics/core-metrics-collectors-server-mocks @elastic/kibana-core +packages/core/metrics/core-metrics-server @elastic/kibana-core +packages/core/metrics/core-metrics-server-internal @elastic/kibana-core +packages/core/metrics/core-metrics-server-mocks @elastic/kibana-core +packages/core/mount-utils/core-mount-utils-browser @elastic/kibana-core +packages/core/mount-utils/core-mount-utils-browser-internal @elastic/kibana-core +packages/core/node/core-node-server @elastic/kibana-core +packages/core/node/core-node-server-internal @elastic/kibana-core +packages/core/node/core-node-server-mocks @elastic/kibana-core +packages/core/notifications/core-notifications-browser @elastic/kibana-core +packages/core/notifications/core-notifications-browser-internal @elastic/kibana-core +packages/core/notifications/core-notifications-browser-mocks @elastic/kibana-core +packages/core/overlays/core-overlays-browser @elastic/kibana-core +packages/core/overlays/core-overlays-browser-internal @elastic/kibana-core +packages/core/overlays/core-overlays-browser-mocks @elastic/kibana-core +packages/core/preboot/core-preboot-server @elastic/kibana-core +packages/core/preboot/core-preboot-server-internal @elastic/kibana-core +packages/core/preboot/core-preboot-server-mocks @elastic/kibana-core +packages/core/rendering/core-rendering-browser-internal @elastic/kibana-core +packages/core/rendering/core-rendering-browser-mocks @elastic/kibana-core +packages/core/saved-objects/core-saved-objects-api-browser @elastic/kibana-core +packages/core/saved-objects/core-saved-objects-api-server @elastic/kibana-core +packages/core/saved-objects/core-saved-objects-api-server-internal @elastic/kibana-core +packages/core/saved-objects/core-saved-objects-api-server-mocks @elastic/kibana-core +packages/core/saved-objects/core-saved-objects-base-server-internal @elastic/kibana-core +packages/core/saved-objects/core-saved-objects-base-server-mocks @elastic/kibana-core +packages/core/saved-objects/core-saved-objects-browser @elastic/kibana-core +packages/core/saved-objects/core-saved-objects-browser-internal @elastic/kibana-core +packages/core/saved-objects/core-saved-objects-browser-mocks @elastic/kibana-core +packages/core/saved-objects/core-saved-objects-common @elastic/kibana-core +packages/core/saved-objects/core-saved-objects-import-export-server-internal @elastic/kibana-core +packages/core/saved-objects/core-saved-objects-import-export-server-mocks @elastic/kibana-core +packages/core/saved-objects/core-saved-objects-migration-server-internal @elastic/kibana-core +packages/core/saved-objects/core-saved-objects-migration-server-mocks @elastic/kibana-core +packages/core/saved-objects/core-saved-objects-server @elastic/kibana-core +packages/core/saved-objects/core-saved-objects-server-internal @elastic/kibana-core +packages/core/saved-objects/core-saved-objects-server-mocks @elastic/kibana-core +packages/core/saved-objects/core-saved-objects-utils-server @elastic/kibana-core +packages/core/status/core-status-common @elastic/kibana-core +packages/core/status/core-status-common-internal @elastic/kibana-core +packages/core/status/core-status-server @elastic/kibana-core +packages/core/status/core-status-server-internal @elastic/kibana-core +packages/core/status/core-status-server-mocks @elastic/kibana-core +packages/core/test-helpers/core-test-helpers-deprecations-getters @elastic/kibana-core +packages/core/test-helpers/core-test-helpers-http-setup-browser @elastic/kibana-core +packages/core/theme/core-theme-browser @elastic/kibana-core +packages/core/theme/core-theme-browser-internal @elastic/kibana-core +packages/core/theme/core-theme-browser-mocks @elastic/kibana-core +packages/core/ui-settings/core-ui-settings-browser @elastic/kibana-core +packages/core/ui-settings/core-ui-settings-browser-internal @elastic/kibana-core +packages/core/ui-settings/core-ui-settings-browser-mocks @elastic/kibana-core +packages/core/ui-settings/core-ui-settings-common @elastic/kibana-core +packages/core/usage-data/core-usage-data-base-server-internal @elastic/kibana-core +packages/core/usage-data/core-usage-data-server @elastic/kibana-core +packages/core/usage-data/core-usage-data-server-internal @elastic/kibana-core +packages/core/usage-data/core-usage-data-server-mocks @elastic/kibana-core +packages/home/sample_data_card @elastic/shared-ux +packages/home/sample_data_tab @elastic/shared-ux +packages/home/sample_data_types @elastic/shared-ux +packages/kbn-ace @elastic/platform-deployment-management +packages/kbn-alerts @elastic/security-solution +packages/kbn-ambient-storybook-types @elastic/kibana-operations +packages/kbn-ambient-ui-types @elastic/kibana-operations +packages/kbn-analytics @elastic/kibana-core +packages/kbn-apm-config-loader @elastic/kibana-core +packages/kbn-apm-synthtrace @elastic/apm-ui +packages/kbn-apm-utils @elastic/apm-ui +packages/kbn-axe-config @elastic/kibana-qa +packages/kbn-babel-plugin-synthetic-packages @elastic/kibana-operations +packages/kbn-babel-preset @elastic/kibana-operations +packages/kbn-bazel-packages @elastic/kibana-operations +packages/kbn-bazel-runner @elastic/kibana-operations +packages/kbn-chart-icons @elastic/kibana-vis-editors +packages/kbn-ci-stats-core @elastic/kibana-operations +packages/kbn-ci-stats-performance-metrics @elastic/kibana-operations +packages/kbn-ci-stats-reporter @elastic/kibana-operations +packages/kbn-cli-dev-mode @elastic/kibana-operations +packages/kbn-coloring @elastic/kibana-vis-editors +packages/kbn-config @elastic/kibana-core +packages/kbn-config-mocks @elastic/kibana-core +packages/kbn-config-schema @elastic/kibana-core +packages/kbn-crypto @elastic/kibana-security +packages/kbn-crypto-browser @elastic/kibana-core +packages/kbn-datemath @elastic/kibana-app-services +packages/kbn-dev-cli-errors @elastic/kibana-operations +packages/kbn-dev-cli-runner @elastic/kibana-operations +packages/kbn-dev-proc-runner @elastic/kibana-operations +packages/kbn-dev-utils @elastic/kibana-operations +packages/kbn-doc-links @elastic/kibana-docs +packages/kbn-docs-utils @elastic/kibana-operations +packages/kbn-ebt-tools @elastic/kibana-core +packages/kbn-es @elastic/kibana-operations +packages/kbn-es-archiver @elastic/kibana-operations +packages/kbn-es-errors @elastic/kibana-core +packages/kbn-es-query @elastic/kibana-app-services +packages/kbn-eslint-config @elastic/kibana-operations +packages/kbn-eslint-plugin-disable @elastic/kibana-operations +packages/kbn-eslint-plugin-eslint @elastic/kibana-operations +packages/kbn-eslint-plugin-imports @elastic/kibana-operations +packages/kbn-expect @elastic/kibana-operations +packages/kbn-field-types @elastic/kibana-app-services +packages/kbn-find-used-node-modules @elastic/kibana-operations +packages/kbn-flot-charts @elastic/kibana-operations +packages/kbn-generate @elastic/kibana-operations +packages/kbn-get-repo-files @elastic/kibana-operations +packages/kbn-handlebars @elastic/kibana-security +packages/kbn-hapi-mocks @elastic/kibana-core +packages/kbn-i18n @elastic/kibana-core +packages/kbn-i18n-react @elastic/kibana-core +packages/kbn-import-resolver @elastic/kibana-operations +packages/kbn-interpreter @elastic/kibana-app-services +packages/kbn-io-ts-utils @elastic/apm-ui +packages/kbn-jest-serializers @elastic/kibana-operations +packages/kbn-kibana-manifest-schema @elastic/kibana-operations +packages/kbn-logging @elastic/kibana-core +packages/kbn-logging-mocks @elastic/kibana-core +packages/kbn-managed-vscode-config @elastic/kibana-operations +packages/kbn-managed-vscode-config-cli @elastic/kibana-operations +packages/kbn-mapbox-gl @elastic/kibana-gis +packages/kbn-monaco @elastic/kibana-app-services +packages/kbn-optimizer @elastic/kibana-operations +packages/kbn-optimizer-webpack-helpers @elastic/kibana-operations +packages/kbn-performance-testing-dataset-extractor @elastic/kibana-performance-testing +packages/kbn-plugin-discovery @elastic/kibana-operations +packages/kbn-plugin-generator @elastic/kibana-operations +packages/kbn-plugin-helpers @elastic/kibana-operations +packages/kbn-react-field @elastic/kibana-app-services +packages/kbn-repo-source-classifier @elastic/kibana-operations +packages/kbn-repo-source-classifier-cli @elastic/kibana-operations +packages/kbn-rule-data-utils @elastic/apm-ui +packages/kbn-safer-lodash-set @elastic/kibana-security +packages/kbn-securitysolution-autocomplete @elastic/security-solution-platform +packages/kbn-securitysolution-es-utils @elastic/security-solution-platform +packages/kbn-securitysolution-hook-utils @elastic/security-solution-platform +packages/kbn-securitysolution-io-ts-alerting-types @elastic/security-solution-platform +packages/kbn-securitysolution-io-ts-list-types @elastic/security-solution-platform +packages/kbn-securitysolution-io-ts-types @elastic/security-solution-platform +packages/kbn-securitysolution-io-ts-utils @elastic/security-solution-platform +packages/kbn-securitysolution-list-api @elastic/security-solution-platform +packages/kbn-securitysolution-list-constants @elastic/security-solution-platform +packages/kbn-securitysolution-list-hooks @elastic/security-solution-platform +packages/kbn-securitysolution-list-utils @elastic/security-solution-platform +packages/kbn-securitysolution-rules @elastic/security-solution-platform +packages/kbn-securitysolution-t-grid @elastic/security-solution-platform +packages/kbn-securitysolution-utils @elastic/security-solution-platform +packages/kbn-server-http-tools @elastic/kibana-core +packages/kbn-server-route-repository @elastic/apm-ui +packages/kbn-shared-svg @elastic/apm-ui +packages/kbn-shared-ux-utility @elastic/shared-ux +packages/kbn-some-dev-log @elastic/kibana-operations +packages/kbn-sort-package-json @elastic/kibana-operations +packages/kbn-spec-to-console @elastic/platform-deployment-management +packages/kbn-std @elastic/kibana-core +packages/kbn-stdio-dev-helpers @elastic/kibana-operations +packages/kbn-storybook @elastic/kibana-operations +packages/kbn-synthetic-package-map @elastic/kibana-operations +packages/kbn-telemetry-tools @elastic/kibana-core +packages/kbn-test @elastic/kibana-operations +packages/kbn-test-jest-helpers @elastic/kibana-operations +packages/kbn-test-subj-selector @elastic/kibana-operations +packages/kbn-timelion-grammar @elastic/kibana-vis-editors +packages/kbn-tinymath @elastic/kibana-vis-editors +packages/kbn-tooling-log @elastic/kibana-operations +packages/kbn-type-summarizer @elastic/kibana-operations +packages/kbn-type-summarizer-cli @elastic/kibana-operations +packages/kbn-type-summarizer-core @elastic/kibana-operations +packages/kbn-typed-react-router-config @elastic/apm-ui +packages/kbn-ui-framework @elastic/kibana-design +packages/kbn-ui-shared-deps-npm @elastic/kibana-operations +packages/kbn-ui-shared-deps-src @elastic/kibana-operations +packages/kbn-ui-theme @elastic/kibana-operations +packages/kbn-user-profile-components @elastic/kibana-security +packages/kbn-utility-types @elastic/kibana-core +packages/kbn-utility-types-jest @elastic/kibana-operations +packages/kbn-utils @elastic/kibana-operations +packages/kbn-yarn-lock-validator @elastic/kibana-operations +packages/shared-ux/avatar/solution @elastic/shared-ux +packages/shared-ux/button_toolbar @elastic/shared-ux +packages/shared-ux/button/exit_full_screen/impl @elastic/shared-ux +packages/shared-ux/button/exit_full_screen/mocks @elastic/shared-ux +packages/shared-ux/button/exit_full_screen/types @elastic/shared-ux +packages/shared-ux/card/no_data/impl @elastic/shared-ux +packages/shared-ux/card/no_data/mocks @elastic/shared-ux +packages/shared-ux/card/no_data/types @elastic/shared-ux +packages/shared-ux/link/redirect_app/impl @elastic/shared-ux +packages/shared-ux/link/redirect_app/mocks @elastic/shared-ux +packages/shared-ux/link/redirect_app/types @elastic/shared-ux +packages/shared-ux/page/analytics_no_data/impl @elastic/shared-ux +packages/shared-ux/page/analytics_no_data/mocks @elastic/shared-ux +packages/shared-ux/page/analytics_no_data/types @elastic/shared-ux +packages/shared-ux/page/kibana_no_data/impl @elastic/shared-ux +packages/shared-ux/page/kibana_no_data/mocks @elastic/shared-ux +packages/shared-ux/page/kibana_no_data/types @elastic/shared-ux +packages/shared-ux/page/kibana_template/impl @elastic/shared-ux +packages/shared-ux/page/kibana_template/mocks @elastic/shared-ux +packages/shared-ux/page/kibana_template/types @elastic/shared-ux +packages/shared-ux/page/no_data_config/impl @elastic/shared-ux +packages/shared-ux/page/no_data_config/mocks @elastic/shared-ux +packages/shared-ux/page/no_data_config/types @elastic/shared-ux +packages/shared-ux/page/no_data/impl @elastic/shared-ux +packages/shared-ux/page/no_data/mocks @elastic/shared-ux +packages/shared-ux/page/no_data/types @elastic/shared-ux +packages/shared-ux/page/solution_nav @elastic/shared-ux +packages/shared-ux/prompt/no_data_views/impl @elastic/shared-ux +packages/shared-ux/prompt/no_data_views/mocks @elastic/shared-ux +packages/shared-ux/prompt/no_data_views/types @elastic/shared-ux +packages/shared-ux/storybook/config @elastic/shared-ux +packages/shared-ux/storybook/mock @elastic/shared-ux +x-pack/packages/ml/agg_utils @elastic/ml-ui +x-pack/packages/ml/aiops_components @elastic/ml-ui +x-pack/packages/ml/aiops_utils @elastic/ml-ui +x-pack/packages/ml/is_populated_object @elastic/ml-ui +x-pack/packages/ml/string_hash @elastic/ml-ui diff --git a/.github/workflows/add-to-apm-project.yml b/.github/workflows/add-to-apm-project.yml index 5df47b56792cd4..8b55449060028b 100644 --- a/.github/workflows/add-to-apm-project.yml +++ b/.github/workflows/add-to-apm-project.yml @@ -12,36 +12,41 @@ jobs: - uses: octokit/graphql-action@v2.x id: add_to_project with: - headers: '{"GraphQL-Features": "projects_next_graphql"}' query: | mutation add_to_project($projectid:ID!,$contentid:ID!) { - addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) { - projectNextItem { - id + addProjectV2ItemById(input:{projectId:$projectid contentId:$contentid}) { + item { + ... on ProjectV2Item { + id + } } } } projectid: ${{ env.PROJECT_ID }} contentid: ${{ github.event.issue.node_id }} env: - PROJECT_ID: "PN_kwDOAGc3Zs0VSg" + PROJECT_ID: "PVT_kwDOAGc3Zs0VSg" GITHUB_TOKEN: ${{ secrets.APM_TECH_KIBANA_USER_TOKEN }} - uses: octokit/graphql-action@v2.x id: label_team with: - headers: '{"GraphQL-Features": "projects_next_graphql"}' query: | mutation label_team($projectid:ID!,$itemid:ID!,$fieldid:ID!,$value:String!) { - updateProjectNextItemField(input: { projectId:$projectid itemId:$itemid fieldId:$fieldid value:$value }) { - projectNextItem { + updateProjectV2ItemFieldValue(input: { projectId:$projectid itemId:$itemid fieldId:$fieldid value:{singleSelectOptionId: $value} }) { + projectV2Item { id + content { + ... on Issue { + number + } + } } } } projectid: ${{ env.PROJECT_ID }} - itemid: ${{ fromJSON(steps.add_to_project.outputs.data).addProjectNextItem.projectNextItem.id }} - fieldid: "MDE2OlByb2plY3ROZXh0RmllbGQ0NDE0Ng==" + itemid: ${{ fromJSON(steps.add_to_project.outputs.data).addProjectV2ItemById.item.id }} + fieldid: "PVTSSF_lADOAGc3Zs0VSs2scg" value: "c33f5c54" env: - PROJECT_ID: "PN_kwDOAGc3Zs0VSg" + PROJECT_ID: "PVT_kwDOAGc3Zs0VSg" GITHUB_TOKEN: ${{ secrets.APM_TECH_KIBANA_USER_TOKEN }} diff --git a/api_docs/actions.mdx b/api_docs/actions.mdx index dadf167e8740e7..7b77296a7abb9d 100644 --- a/api_docs/actions.mdx +++ b/api_docs/actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/actions title: "actions" image: https://source.unsplash.com/400x175/?github description: API docs for the actions plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'actions'] --- import actionsObj from './actions.devdocs.json'; diff --git a/api_docs/advanced_settings.mdx b/api_docs/advanced_settings.mdx index bff8c3b8250611..8497e2ae833d52 100644 --- a/api_docs/advanced_settings.mdx +++ b/api_docs/advanced_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/advancedSettings title: "advancedSettings" image: https://source.unsplash.com/400x175/?github description: API docs for the advancedSettings plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'advancedSettings'] --- import advancedSettingsObj from './advanced_settings.devdocs.json'; diff --git a/api_docs/aiops.devdocs.json b/api_docs/aiops.devdocs.json index d1fca06df35b76..ec6cbc92588124 100644 --- a/api_docs/aiops.devdocs.json +++ b/api_docs/aiops.devdocs.json @@ -48,25 +48,7 @@ "interfaces": [], "enums": [], "misc": [], - "objects": [], - "start": { - "parentPluginId": "aiops", - "id": "def-public.AiopsPluginStart", - "type": "Type", - "tags": [], - "label": "AiopsPluginStart", - "description": [ - "\naiops plugin public start contract" - ], - "signature": [ - "void" - ], - "path": "x-pack/plugins/aiops/public/types.ts", - "deprecated": false, - "trackAdoption": false, - "lifecycle": "start", - "initialIsOpen": true - } + "objects": [] }, "server": { "classes": [], diff --git a/api_docs/aiops.mdx b/api_docs/aiops.mdx index 689c0f3dea5c1c..28fd735f6e461e 100644 --- a/api_docs/aiops.mdx +++ b/api_docs/aiops.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/aiops title: "aiops" image: https://source.unsplash.com/400x175/?github description: API docs for the aiops plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'aiops'] --- import aiopsObj from './aiops.devdocs.json'; @@ -21,13 +21,10 @@ Contact [Machine Learning UI](https://github.com/orgs/elastic/teams/ml-ui) for q | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 9 | 0 | 0 | 1 | +| 7 | 0 | 0 | 1 | ## Client -### Start - - ### Functions diff --git a/api_docs/alerting.mdx b/api_docs/alerting.mdx index a05850bed5d32a..d331897a74bc21 100644 --- a/api_docs/alerting.mdx +++ b/api_docs/alerting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/alerting title: "alerting" image: https://source.unsplash.com/400x175/?github description: API docs for the alerting plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'alerting'] --- import alertingObj from './alerting.devdocs.json'; diff --git a/api_docs/apm.devdocs.json b/api_docs/apm.devdocs.json index f5b4ceba305d8f..efaf84a5b304a1 100644 --- a/api_docs/apm.devdocs.json +++ b/api_docs/apm.devdocs.json @@ -792,7 +792,7 @@ "label": "APIEndpoint", "description": [], "signature": [ - "\"POST /internal/apm/data_view/static\" | \"GET /internal/apm/data_view/title\" | \"GET /internal/apm/environments\" | \"GET /internal/apm/services/{serviceName}/errors/groups/main_statistics\" | \"GET /internal/apm/services/{serviceName}/errors/groups/main_statistics_by_transaction_name\" | \"POST /internal/apm/services/{serviceName}/errors/groups/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/errors/{groupId}\" | \"GET /internal/apm/services/{serviceName}/errors/distribution\" | \"GET /internal/apm/services/{serviceName}/errors/{groupId}/top_erroneous_transactions\" | \"POST /internal/apm/latency/overall_distribution/transactions\" | \"GET /internal/apm/services/{serviceName}/metrics/charts\" | \"GET /internal/apm/observability_overview\" | \"GET /internal/apm/observability_overview/has_data\" | \"GET /internal/apm/service-map\" | \"GET /internal/apm/service-map/service/{serviceName}\" | \"GET /internal/apm/service-map/dependency\" | \"GET /internal/apm/services/{serviceName}/serviceNodes\" | \"GET /internal/apm/services\" | \"POST /internal/apm/services/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/metadata/details\" | \"GET /internal/apm/services/{serviceName}/metadata/icons\" | \"GET /internal/apm/services/{serviceName}/agent\" | \"GET /internal/apm/services/{serviceName}/transaction_types\" | \"GET /internal/apm/services/{serviceName}/node/{serviceNodeName}/metadata\" | \"GET /api/apm/services/{serviceName}/annotation/search\" | \"POST /api/apm/services/{serviceName}/annotation\" | \"GET /internal/apm/services/{serviceName}/service_overview_instances/details/{serviceNodeName}\" | \"GET /internal/apm/services/{serviceName}/throughput\" | \"GET /internal/apm/services/{serviceName}/service_overview_instances/main_statistics\" | \"GET /internal/apm/services/{serviceName}/service_overview_instances/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/dependencies\" | \"GET /internal/apm/services/{serviceName}/dependencies/breakdown\" | \"GET /internal/apm/services/{serviceName}/profiling/timeline\" | \"GET /internal/apm/services/{serviceName}/profiling/statistics\" | \"GET /internal/apm/services/{serviceName}/anomaly_charts\" | \"GET /internal/apm/sorted_and_filtered_services\" | \"GET /internal/apm/service-groups\" | \"GET /internal/apm/service-group\" | \"POST /internal/apm/service-group\" | \"DELETE /internal/apm/service-group\" | \"GET /internal/apm/service-group/services\" | \"GET /internal/apm/suggestions\" | \"GET /internal/apm/traces/{traceId}\" | \"GET /internal/apm/traces\" | \"GET /internal/apm/traces/{traceId}/root_transaction\" | \"GET /internal/apm/transactions/{transactionId}\" | \"GET /internal/apm/traces/find\" | \"GET /internal/apm/services/{serviceName}/transactions/groups/main_statistics\" | \"GET /internal/apm/services/{serviceName}/transactions/groups/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/latency\" | \"GET /internal/apm/services/{serviceName}/transactions/traces/samples\" | \"GET /internal/apm/services/{serviceName}/transaction/charts/breakdown\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/error_rate\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/coldstart_rate\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/coldstart_rate_by_transaction_name\" | \"GET /internal/apm/alerts/chart_preview/transaction_error_rate\" | \"GET /internal/apm/alerts/chart_preview/transaction_duration\" | \"GET /internal/apm/alerts/chart_preview/transaction_error_count\" | \"GET /api/apm/settings/agent-configuration\" | \"GET /api/apm/settings/agent-configuration/view\" | \"DELETE /api/apm/settings/agent-configuration\" | \"PUT /api/apm/settings/agent-configuration\" | \"POST /api/apm/settings/agent-configuration/search\" | \"GET /api/apm/settings/agent-configuration/environments\" | \"GET /api/apm/settings/agent-configuration/agent_name\" | \"GET /internal/apm/settings/anomaly-detection/jobs\" | \"POST /internal/apm/settings/anomaly-detection/jobs\" | \"GET /internal/apm/settings/anomaly-detection/environments\" | \"POST /internal/apm/settings/anomaly-detection/update_to_v3\" | \"GET /internal/apm/settings/apm-index-settings\" | \"GET /internal/apm/settings/apm-indices\" | \"POST /internal/apm/settings/apm-indices/save\" | \"GET /internal/apm/settings/custom_links/transaction\" | \"GET /internal/apm/settings/custom_links\" | \"POST /internal/apm/settings/custom_links\" | \"PUT /internal/apm/settings/custom_links/{id}\" | \"DELETE /internal/apm/settings/custom_links/{id}\" | \"GET /api/apm/sourcemaps\" | \"POST /api/apm/sourcemaps\" | \"DELETE /api/apm/sourcemaps/{id}\" | \"GET /internal/apm/fleet/has_apm_policies\" | \"GET /internal/apm/fleet/agents\" | \"POST /api/apm/fleet/apm_server_schema\" | \"GET /internal/apm/fleet/apm_server_schema/unsupported\" | \"GET /internal/apm/fleet/migration_check\" | \"POST /internal/apm/fleet/cloud_apm_package_policy\" | \"GET /internal/apm/fleet/java_agent_versions\" | \"GET /internal/apm/dependencies/top_dependencies\" | \"GET /internal/apm/dependencies/upstream_services\" | \"GET /internal/apm/dependencies/metadata\" | \"GET /internal/apm/dependencies/charts/latency\" | \"GET /internal/apm/dependencies/charts/throughput\" | \"GET /internal/apm/dependencies/charts/error_rate\" | \"GET /internal/apm/dependencies/operations\" | \"GET /internal/apm/dependencies/charts/distribution\" | \"GET /internal/apm/dependencies/operations/spans\" | \"GET /internal/apm/correlations/field_candidates/transactions\" | \"POST /internal/apm/correlations/field_stats/transactions\" | \"GET /internal/apm/correlations/field_value_stats/transactions\" | \"POST /internal/apm/correlations/field_value_pairs/transactions\" | \"POST /internal/apm/correlations/significant_correlations/transactions\" | \"POST /internal/apm/correlations/p_values/transactions\" | \"GET /internal/apm/fallback_to_transactions\" | \"GET /internal/apm/has_data\" | \"GET /internal/apm/event_metadata/{processorEvent}/{id}\" | \"GET /internal/apm/agent_keys\" | \"GET /internal/apm/agent_keys/privileges\" | \"POST /internal/apm/api_key/invalidate\" | \"POST /api/apm/agent_keys\" | \"GET /internal/apm/storage_explorer\" | \"GET /internal/apm/services/{serviceName}/storage_details\" | \"GET /internal/apm/traces/{traceId}/span_links/{spanId}/parents\" | \"GET /internal/apm/traces/{traceId}/span_links/{spanId}/children\" | \"GET /internal/apm/services/{serviceName}/infrastructure_attributes\" | \"GET /internal/apm/debug-telemetry\" | \"GET /internal/apm/time_range_metadata\"" + "\"POST /internal/apm/data_view/static\" | \"GET /internal/apm/data_view/title\" | \"GET /internal/apm/environments\" | \"GET /internal/apm/services/{serviceName}/errors/groups/main_statistics\" | \"GET /internal/apm/services/{serviceName}/errors/groups/main_statistics_by_transaction_name\" | \"POST /internal/apm/services/{serviceName}/errors/groups/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/errors/{groupId}\" | \"GET /internal/apm/services/{serviceName}/errors/distribution\" | \"GET /internal/apm/services/{serviceName}/errors/{groupId}/top_erroneous_transactions\" | \"POST /internal/apm/latency/overall_distribution/transactions\" | \"GET /internal/apm/services/{serviceName}/metrics/charts\" | \"GET /internal/apm/observability_overview\" | \"GET /internal/apm/observability_overview/has_data\" | \"GET /internal/apm/service-map\" | \"GET /internal/apm/service-map/service/{serviceName}\" | \"GET /internal/apm/service-map/dependency\" | \"GET /internal/apm/services/{serviceName}/serviceNodes\" | \"GET /internal/apm/services\" | \"POST /internal/apm/services/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/metadata/details\" | \"GET /internal/apm/services/{serviceName}/metadata/icons\" | \"GET /internal/apm/services/{serviceName}/agent\" | \"GET /internal/apm/services/{serviceName}/transaction_types\" | \"GET /internal/apm/services/{serviceName}/node/{serviceNodeName}/metadata\" | \"GET /api/apm/services/{serviceName}/annotation/search\" | \"POST /api/apm/services/{serviceName}/annotation\" | \"GET /internal/apm/services/{serviceName}/service_overview_instances/details/{serviceNodeName}\" | \"GET /internal/apm/services/{serviceName}/throughput\" | \"GET /internal/apm/services/{serviceName}/service_overview_instances/main_statistics\" | \"GET /internal/apm/services/{serviceName}/service_overview_instances/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/dependencies\" | \"GET /internal/apm/services/{serviceName}/dependencies/breakdown\" | \"GET /internal/apm/services/{serviceName}/profiling/timeline\" | \"GET /internal/apm/services/{serviceName}/profiling/statistics\" | \"GET /internal/apm/services/{serviceName}/anomaly_charts\" | \"GET /internal/apm/sorted_and_filtered_services\" | \"GET /internal/apm/service-groups\" | \"GET /internal/apm/service-group\" | \"POST /internal/apm/service-group\" | \"DELETE /internal/apm/service-group\" | \"GET /internal/apm/service-group/services\" | \"GET /internal/apm/suggestions\" | \"GET /internal/apm/traces/{traceId}\" | \"GET /internal/apm/traces\" | \"GET /internal/apm/traces/{traceId}/root_transaction\" | \"GET /internal/apm/transactions/{transactionId}\" | \"GET /internal/apm/traces/find\" | \"GET /internal/apm/services/{serviceName}/transactions/groups/main_statistics\" | \"GET /internal/apm/services/{serviceName}/transactions/groups/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/latency\" | \"GET /internal/apm/services/{serviceName}/transactions/traces/samples\" | \"GET /internal/apm/services/{serviceName}/transaction/charts/breakdown\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/error_rate\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/coldstart_rate\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/coldstart_rate_by_transaction_name\" | \"GET /internal/apm/alerts/chart_preview/transaction_error_rate\" | \"GET /internal/apm/alerts/chart_preview/transaction_duration\" | \"GET /internal/apm/alerts/chart_preview/transaction_error_count\" | \"GET /api/apm/settings/agent-configuration\" | \"GET /api/apm/settings/agent-configuration/view\" | \"DELETE /api/apm/settings/agent-configuration\" | \"PUT /api/apm/settings/agent-configuration\" | \"POST /api/apm/settings/agent-configuration/search\" | \"GET /api/apm/settings/agent-configuration/environments\" | \"GET /api/apm/settings/agent-configuration/agent_name\" | \"GET /internal/apm/settings/anomaly-detection/jobs\" | \"POST /internal/apm/settings/anomaly-detection/jobs\" | \"GET /internal/apm/settings/anomaly-detection/environments\" | \"POST /internal/apm/settings/anomaly-detection/update_to_v3\" | \"GET /internal/apm/settings/apm-index-settings\" | \"GET /internal/apm/settings/apm-indices\" | \"POST /internal/apm/settings/apm-indices/save\" | \"GET /internal/apm/settings/custom_links/transaction\" | \"GET /internal/apm/settings/custom_links\" | \"POST /internal/apm/settings/custom_links\" | \"PUT /internal/apm/settings/custom_links/{id}\" | \"DELETE /internal/apm/settings/custom_links/{id}\" | \"GET /api/apm/sourcemaps\" | \"POST /api/apm/sourcemaps\" | \"DELETE /api/apm/sourcemaps/{id}\" | \"GET /internal/apm/fleet/has_apm_policies\" | \"GET /internal/apm/fleet/agents\" | \"POST /api/apm/fleet/apm_server_schema\" | \"GET /internal/apm/fleet/apm_server_schema/unsupported\" | \"GET /internal/apm/fleet/migration_check\" | \"POST /internal/apm/fleet/cloud_apm_package_policy\" | \"GET /internal/apm/fleet/java_agent_versions\" | \"GET /internal/apm/dependencies/top_dependencies\" | \"GET /internal/apm/dependencies/upstream_services\" | \"GET /internal/apm/dependencies/metadata\" | \"GET /internal/apm/dependencies/charts/latency\" | \"GET /internal/apm/dependencies/charts/throughput\" | \"GET /internal/apm/dependencies/charts/error_rate\" | \"GET /internal/apm/dependencies/operations\" | \"GET /internal/apm/dependencies/charts/distribution\" | \"GET /internal/apm/dependencies/operations/spans\" | \"GET /internal/apm/correlations/field_candidates/transactions\" | \"POST /internal/apm/correlations/field_stats/transactions\" | \"GET /internal/apm/correlations/field_value_stats/transactions\" | \"POST /internal/apm/correlations/field_value_pairs/transactions\" | \"POST /internal/apm/correlations/significant_correlations/transactions\" | \"POST /internal/apm/correlations/p_values/transactions\" | \"GET /internal/apm/fallback_to_transactions\" | \"GET /internal/apm/has_data\" | \"GET /internal/apm/event_metadata/{processorEvent}/{id}\" | \"GET /internal/apm/agent_keys\" | \"GET /internal/apm/agent_keys/privileges\" | \"POST /internal/apm/api_key/invalidate\" | \"POST /api/apm/agent_keys\" | \"GET /internal/apm/storage_explorer\" | \"GET /internal/apm/services/{serviceName}/storage_details\" | \"GET /internal/apm/storage_chart\" | \"GET /internal/apm/traces/{traceId}/span_links/{spanId}/parents\" | \"GET /internal/apm/traces/{traceId}/span_links/{spanId}/children\" | \"GET /internal/apm/services/{serviceName}/infrastructure_attributes\" | \"GET /internal/apm/debug-telemetry\" | \"GET /internal/apm/time_range_metadata\"" ], "path": "x-pack/plugins/apm/server/routes/apm_routes/get_global_apm_server_route_repository.ts", "deprecated": false, @@ -1064,6 +1064,74 @@ "SpanLinkDetails", "[]; }, ", "APMRouteCreateOptions", + ">; \"GET /internal/apm/storage_chart\": ", + "ServerRoute", + "<\"GET /internal/apm/storage_chart\", ", + "TypeC", + "<{ query: ", + "IntersectionC", + "<[", + "TypeC", + "<{ indexLifecyclePhase: ", + "UnionC", + "<[", + "LiteralC", + "<", + "IndexLifecyclePhaseSelectOption", + ".All>, ", + "LiteralC", + "<", + "IndexLifecyclePhaseSelectOption", + ".Hot>, ", + "LiteralC", + "<", + "IndexLifecyclePhaseSelectOption", + ".Warm>, ", + "LiteralC", + "<", + "IndexLifecyclePhaseSelectOption", + ".Cold>, ", + "LiteralC", + "<", + "IndexLifecyclePhaseSelectOption", + ".Frozen>]>; }>, ", + "TypeC", + "<{ probability: ", + "Type", + "; }>, ", + "TypeC", + "<{ environment: ", + "UnionC", + "<[", + "LiteralC", + "<\"ENVIRONMENT_NOT_DEFINED\">, ", + "LiteralC", + "<\"ENVIRONMENT_ALL\">, ", + "BrandC", + "<", + "StringC", + ", ", + "NonEmptyStringBrand", + ">]>; }>, ", + "TypeC", + "<{ kuery: ", + "StringC", + "; }>, ", + "TypeC", + "<{ start: ", + "Type", + "; end: ", + "Type", + "; }>]>; }>, ", + { + "pluginId": "apm", + "scope": "server", + "docId": "kibApmPluginApi", + "section": "def-server.APMRouteHandlerResources", + "text": "APMRouteHandlerResources" + }, + ", { storageTimeSeries: { serviceName: string; timeseries: { x: number; y: number; }[]; }[]; }, ", + "APMRouteCreateOptions", ">; \"GET /internal/apm/services/{serviceName}/storage_details\": ", "ServerRoute", "<\"GET /internal/apm/services/{serviceName}/storage_details\", ", diff --git a/api_docs/apm.mdx b/api_docs/apm.mdx index 25fe4d5efea105..27c873e1cbc08c 100644 --- a/api_docs/apm.mdx +++ b/api_docs/apm.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/apm title: "apm" image: https://source.unsplash.com/400x175/?github description: API docs for the apm plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'apm'] --- import apmObj from './apm.devdocs.json'; diff --git a/api_docs/banners.mdx b/api_docs/banners.mdx index 78291085e75c2c..167582665bb6d3 100644 --- a/api_docs/banners.mdx +++ b/api_docs/banners.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/banners title: "banners" image: https://source.unsplash.com/400x175/?github description: API docs for the banners plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'banners'] --- import bannersObj from './banners.devdocs.json'; diff --git a/api_docs/bfetch.mdx b/api_docs/bfetch.mdx index 3aa8cd01a8314d..363cb213dfa2c9 100644 --- a/api_docs/bfetch.mdx +++ b/api_docs/bfetch.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/bfetch title: "bfetch" image: https://source.unsplash.com/400x175/?github description: API docs for the bfetch plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'bfetch'] --- import bfetchObj from './bfetch.devdocs.json'; diff --git a/api_docs/canvas.mdx b/api_docs/canvas.mdx index 2f71a9aa930fa5..2910180b02cdf0 100644 --- a/api_docs/canvas.mdx +++ b/api_docs/canvas.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/canvas title: "canvas" image: https://source.unsplash.com/400x175/?github description: API docs for the canvas plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'canvas'] --- import canvasObj from './canvas.devdocs.json'; diff --git a/api_docs/cases.mdx b/api_docs/cases.mdx index 5f4998268d3344..cbc8bc0dcfd440 100644 --- a/api_docs/cases.mdx +++ b/api_docs/cases.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cases title: "cases" image: https://source.unsplash.com/400x175/?github description: API docs for the cases plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cases'] --- import casesObj from './cases.devdocs.json'; diff --git a/api_docs/charts.devdocs.json b/api_docs/charts.devdocs.json index 18bb2aa2a806ab..7131b518535f32 100644 --- a/api_docs/charts.devdocs.json +++ b/api_docs/charts.devdocs.json @@ -670,6 +670,51 @@ "children": [], "returnComment": [], "initialIsOpen": false + }, + { + "parentPluginId": "charts", + "id": "def-public.Warnings", + "type": "Function", + "tags": [], + "label": "Warnings", + "description": [], + "signature": [ + "({ warnings }: { warnings: React.ReactNode[]; }) => JSX.Element | null" + ], + "path": "src/plugins/charts/public/static/components/warnings.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "charts", + "id": "def-public.Warnings.$1", + "type": "Object", + "tags": [], + "label": "{ warnings }", + "description": [], + "path": "src/plugins/charts/public/static/components/warnings.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "charts", + "id": "def-public.Warnings.$1.warnings", + "type": "Array", + "tags": [], + "label": "warnings", + "description": [], + "signature": [ + "React.ReactNode[]" + ], + "path": "src/plugins/charts/public/static/components/warnings.tsx", + "deprecated": false, + "trackAdoption": false + } + ] + } + ], + "returnComment": [], + "initialIsOpen": false } ], "interfaces": [ diff --git a/api_docs/charts.mdx b/api_docs/charts.mdx index 0d3e659e8b7850..ca9fc19e1213bb 100644 --- a/api_docs/charts.mdx +++ b/api_docs/charts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/charts title: "charts" image: https://source.unsplash.com/400x175/?github description: API docs for the charts plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'charts'] --- import chartsObj from './charts.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 261 | 2 | 246 | 9 | +| 264 | 2 | 249 | 9 | ## Client diff --git a/api_docs/cloud.mdx b/api_docs/cloud.mdx index 14a4c1d38c53ee..bffc54e20d6abc 100644 --- a/api_docs/cloud.mdx +++ b/api_docs/cloud.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloud title: "cloud" image: https://source.unsplash.com/400x175/?github description: API docs for the cloud plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloud'] --- import cloudObj from './cloud.devdocs.json'; diff --git a/api_docs/cloud_security_posture.mdx b/api_docs/cloud_security_posture.mdx index 5a3a2a236e7fc9..40ee284d2734c8 100644 --- a/api_docs/cloud_security_posture.mdx +++ b/api_docs/cloud_security_posture.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudSecurityPosture title: "cloudSecurityPosture" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudSecurityPosture plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudSecurityPosture'] --- import cloudSecurityPostureObj from './cloud_security_posture.devdocs.json'; diff --git a/api_docs/console.mdx b/api_docs/console.mdx index 3df1c839b0f08d..88390589d38352 100644 --- a/api_docs/console.mdx +++ b/api_docs/console.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/console title: "console" image: https://source.unsplash.com/400x175/?github description: API docs for the console plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'console'] --- import consoleObj from './console.devdocs.json'; diff --git a/api_docs/controls.mdx b/api_docs/controls.mdx index d29e799e72fd0b..ae609d41255ab2 100644 --- a/api_docs/controls.mdx +++ b/api_docs/controls.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/controls title: "controls" image: https://source.unsplash.com/400x175/?github description: API docs for the controls plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'controls'] --- import controlsObj from './controls.devdocs.json'; diff --git a/api_docs/core.mdx b/api_docs/core.mdx index 541ca6affdbc5a..1bd545035359a8 100644 --- a/api_docs/core.mdx +++ b/api_docs/core.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/core title: "core" image: https://source.unsplash.com/400x175/?github description: API docs for the core plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'core'] --- import coreObj from './core.devdocs.json'; diff --git a/api_docs/custom_integrations.mdx b/api_docs/custom_integrations.mdx index d2c87cab417d38..daf36243e408dd 100644 --- a/api_docs/custom_integrations.mdx +++ b/api_docs/custom_integrations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/customIntegrations title: "customIntegrations" image: https://source.unsplash.com/400x175/?github description: API docs for the customIntegrations plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'customIntegrations'] --- import customIntegrationsObj from './custom_integrations.devdocs.json'; diff --git a/api_docs/dashboard.mdx b/api_docs/dashboard.mdx index 9cc5265026ffbd..d7da06c8bda6e6 100644 --- a/api_docs/dashboard.mdx +++ b/api_docs/dashboard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dashboard title: "dashboard" image: https://source.unsplash.com/400x175/?github description: API docs for the dashboard plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboard'] --- import dashboardObj from './dashboard.devdocs.json'; diff --git a/api_docs/dashboard_enhanced.mdx b/api_docs/dashboard_enhanced.mdx index 45a942a1b27f06..7e58cc9e1a86a4 100644 --- a/api_docs/dashboard_enhanced.mdx +++ b/api_docs/dashboard_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dashboardEnhanced title: "dashboardEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the dashboardEnhanced plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboardEnhanced'] --- import dashboardEnhancedObj from './dashboard_enhanced.devdocs.json'; diff --git a/api_docs/data.mdx b/api_docs/data.mdx index d3115cfccb73cf..f7f878ec5cf745 100644 --- a/api_docs/data.mdx +++ b/api_docs/data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data title: "data" image: https://source.unsplash.com/400x175/?github description: API docs for the data plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data'] --- import dataObj from './data.devdocs.json'; @@ -21,7 +21,7 @@ Contact [App Services](https://github.com/orgs/elastic/teams/kibana-app-services | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 3131 | 34 | 2441 | 23 | +| 3144 | 34 | 2444 | 23 | ## Client diff --git a/api_docs/data_query.mdx b/api_docs/data_query.mdx index acc0894eabca62..5206f1ec467308 100644 --- a/api_docs/data_query.mdx +++ b/api_docs/data_query.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data-query title: "data.query" image: https://source.unsplash.com/400x175/?github description: API docs for the data.query plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.query'] --- import dataQueryObj from './data_query.devdocs.json'; @@ -21,7 +21,7 @@ Contact [App Services](https://github.com/orgs/elastic/teams/kibana-app-services | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 3131 | 34 | 2441 | 23 | +| 3144 | 34 | 2444 | 23 | ## Client diff --git a/api_docs/data_search.devdocs.json b/api_docs/data_search.devdocs.json index 652737b0a23a45..399c9e5b7f1881 100644 --- a/api_docs/data_search.devdocs.json +++ b/api_docs/data_search.devdocs.json @@ -10605,6 +10605,281 @@ } ], "initialIsOpen": false + }, + { + "parentPluginId": "data", + "id": "def-common.TimeBuckets", + "type": "Class", + "tags": [], + "label": "TimeBuckets", + "description": [ + "\nHelper class for wrapping the concept of an \"Interval\",\nwhich describes a timespan that will separate moments.\n" + ], + "path": "src/plugins/data/common/search/aggs/buckets/lib/time_buckets/time_buckets.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-common.TimeBuckets.Unnamed", + "type": "Function", + "tags": [], + "label": "Constructor", + "description": [], + "signature": [ + "any" + ], + "path": "src/plugins/data/common/search/aggs/buckets/lib/time_buckets/time_buckets.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-common.TimeBuckets.Unnamed.$1", + "type": "Object", + "tags": [], + "label": "timeBucketConfig", + "description": [], + "signature": [ + "TimeBucketsConfig" + ], + "path": "src/plugins/data/common/search/aggs/buckets/lib/time_buckets/time_buckets.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-common.TimeBuckets.setBounds", + "type": "Function", + "tags": [], + "label": "setBounds", + "description": [ + "\nSet the bounds that these buckets are expected to cover.\nThis is required to support interval \"auto\" as well\nas interval scaling.\n" + ], + "signature": [ + "(input?: ", + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataQueryPluginApi", + "section": "def-common.TimeRangeBounds", + "text": "TimeRangeBounds" + }, + " | ", + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataQueryPluginApi", + "section": "def-common.TimeRangeBounds", + "text": "TimeRangeBounds" + }, + "[] | undefined) => void" + ], + "path": "src/plugins/data/common/search/aggs/buckets/lib/time_buckets/time_buckets.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-common.TimeBuckets.setBounds.$1", + "type": "CompoundType", + "tags": [], + "label": "input", + "description": [ + "- an object with properties min and max,\nrepresenting the edges for the time span\nwe should cover" + ], + "signature": [ + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataQueryPluginApi", + "section": "def-common.TimeRangeBounds", + "text": "TimeRangeBounds" + }, + " | ", + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataQueryPluginApi", + "section": "def-common.TimeRangeBounds", + "text": "TimeRangeBounds" + }, + "[] | undefined" + ], + "path": "src/plugins/data/common/search/aggs/buckets/lib/time_buckets/time_buckets.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-common.TimeBuckets.clearBounds", + "type": "Function", + "tags": [ + "return" + ], + "label": "clearBounds", + "description": [ + "\nClear the stored bounds\n" + ], + "signature": [ + "() => void" + ], + "path": "src/plugins/data/common/search/aggs/buckets/lib/time_buckets/time_buckets.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-common.TimeBuckets.hasBounds", + "type": "Function", + "tags": [ + "return" + ], + "label": "hasBounds", + "description": [ + "\nCheck to see if we have received bounds yet\n" + ], + "signature": [ + "() => boolean" + ], + "path": "src/plugins/data/common/search/aggs/buckets/lib/time_buckets/time_buckets.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-common.TimeBuckets.getBounds", + "type": "Function", + "tags": [ + "return" + ], + "label": "getBounds", + "description": [ + "\nReturn the current bounds, if we have any.\n\nTHIS DOES NOT CLONE THE BOUNDS, so editing them\nmay have unexpected side-effects. Always\ncall bounds.min.clone() before editing\n" + ], + "signature": [ + "() => ", + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataQueryPluginApi", + "section": "def-common.TimeRangeBounds", + "text": "TimeRangeBounds" + }, + " | undefined" + ], + "path": "src/plugins/data/common/search/aggs/buckets/lib/time_buckets/time_buckets.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [ + "- If bounds are not defined, this\nreturns undefined, else it returns the bounds\nfor these buckets. This object has two props,\nmin and max. Each property will be a moment()\nobject" + ] + }, + { + "parentPluginId": "data", + "id": "def-common.TimeBuckets.setInterval", + "type": "Function", + "tags": [], + "label": "setInterval", + "description": [ + "\nUpdate the interval at which buckets should be\ngenerated.\n\nInput can be one of the following:\n - Any object from src/legacy/ui/agg_types.js\n - \"auto\"\n - Pass a valid moment unit\n" + ], + "signature": [ + "(input: string | Record | null) => void" + ], + "path": "src/plugins/data/common/search/aggs/buckets/lib/time_buckets/time_buckets.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-common.TimeBuckets.setInterval.$1", + "type": "CompoundType", + "tags": [], + "label": "input", + "description": [ + "- see desc" + ], + "signature": [ + "string | Record | null" + ], + "path": "src/plugins/data/common/search/aggs/buckets/lib/time_buckets/time_buckets.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-common.TimeBuckets.getInterval", + "type": "Function", + "tags": [], + "label": "getInterval", + "description": [ + "\nGet the interval for the buckets. If the\nnumber of buckets created by the interval set\nis larger than config:histogram:maxBars then the\ninterval will be scaled up. If the number of buckets\ncreated is less than one, the interval is scaled back.\n\nThe interval object returned is a moment.duration\nobject that has been decorated with the following\nproperties.\n\ninterval.description: a text description of the interval.\n designed to be used list \"field per {{ desc }}\".\n - \"minute\"\n - \"10 days\"\n - \"3 years\"\n\ninterval.expression: the elasticsearch expression that creates this\n interval. If the interval does not properly form an elasticsearch\n expression it will be forced into one.\n\ninterval.scaled: the interval was adjusted to\n accommodate the maxBars setting.\n\ninterval.scale: the number that y-values should be\n multiplied by" + ], + "signature": [ + "(useNormalizedEsInterval?: boolean) => TimeBucketsInterval" + ], + "path": "src/plugins/data/common/search/aggs/buckets/lib/time_buckets/time_buckets.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-common.TimeBuckets.getInterval.$1", + "type": "boolean", + "tags": [], + "label": "useNormalizedEsInterval", + "description": [], + "signature": [ + "boolean" + ], + "path": "src/plugins/data/common/search/aggs/buckets/lib/time_buckets/time_buckets.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-common.TimeBuckets.getScaledDateFormat", + "type": "Function", + "tags": [ + "return" + ], + "label": "getScaledDateFormat", + "description": [ + "\nGet a date format string that will represent dates that\nprogress at our interval.\n\nSince our interval can be as small as 1ms, the default\ndate format is usually way too much. with `dateFormat:scaled`\nusers can modify how dates are formatted within series\nproduced by TimeBuckets\n" + ], + "signature": [ + "() => string" + ], + "path": "src/plugins/data/common/search/aggs/buckets/lib/time_buckets/time_buckets.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + } + ], + "initialIsOpen": false } ], "functions": [ @@ -24123,7 +24398,13 @@ "label": "buckets", "description": [], "signature": [ - "TimeBuckets" + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.TimeBuckets", + "text": "TimeBuckets" + } ], "path": "src/plugins/data/common/search/aggs/buckets/date_histogram.ts", "deprecated": false, diff --git a/api_docs/data_search.mdx b/api_docs/data_search.mdx index 1eb654fe6b51ad..948da55a39f746 100644 --- a/api_docs/data_search.mdx +++ b/api_docs/data_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data-search title: "data.search" image: https://source.unsplash.com/400x175/?github description: API docs for the data.search plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.search'] --- import dataSearchObj from './data_search.devdocs.json'; @@ -21,7 +21,7 @@ Contact [App Services](https://github.com/orgs/elastic/teams/kibana-app-services | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 3131 | 34 | 2441 | 23 | +| 3144 | 34 | 2444 | 23 | ## Client diff --git a/api_docs/data_view_editor.mdx b/api_docs/data_view_editor.mdx index 06a7e6674ad4c0..95fa4182594f84 100644 --- a/api_docs/data_view_editor.mdx +++ b/api_docs/data_view_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewEditor title: "dataViewEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewEditor plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewEditor'] --- import dataViewEditorObj from './data_view_editor.devdocs.json'; diff --git a/api_docs/data_view_field_editor.mdx b/api_docs/data_view_field_editor.mdx index f5aac30bac5719..19de55351a8de5 100644 --- a/api_docs/data_view_field_editor.mdx +++ b/api_docs/data_view_field_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewFieldEditor title: "dataViewFieldEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewFieldEditor plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewFieldEditor'] --- import dataViewFieldEditorObj from './data_view_field_editor.devdocs.json'; diff --git a/api_docs/data_view_management.mdx b/api_docs/data_view_management.mdx index 02ba97f2334248..b1851139b7d9e3 100644 --- a/api_docs/data_view_management.mdx +++ b/api_docs/data_view_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewManagement title: "dataViewManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewManagement plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewManagement'] --- import dataViewManagementObj from './data_view_management.devdocs.json'; diff --git a/api_docs/data_views.mdx b/api_docs/data_views.mdx index 5166413c81d6a8..892d584ba199e2 100644 --- a/api_docs/data_views.mdx +++ b/api_docs/data_views.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViews title: "dataViews" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViews plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViews'] --- import dataViewsObj from './data_views.devdocs.json'; diff --git a/api_docs/data_visualizer.mdx b/api_docs/data_visualizer.mdx index 0f90354db488e7..2dd8caad2c6552 100644 --- a/api_docs/data_visualizer.mdx +++ b/api_docs/data_visualizer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataVisualizer title: "dataVisualizer" image: https://source.unsplash.com/400x175/?github description: API docs for the dataVisualizer plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataVisualizer'] --- import dataVisualizerObj from './data_visualizer.devdocs.json'; diff --git a/api_docs/deprecations_by_api.mdx b/api_docs/deprecations_by_api.mdx index 4b61218ebf7686..df2ac0366eadfe 100644 --- a/api_docs/deprecations_by_api.mdx +++ b/api_docs/deprecations_by_api.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsByApi slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-api title: Deprecated API usage by API description: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by. -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/deprecations_by_plugin.mdx b/api_docs/deprecations_by_plugin.mdx index d9da58e4a98dd6..600739e4a9fdee 100644 --- a/api_docs/deprecations_by_plugin.mdx +++ b/api_docs/deprecations_by_plugin.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsByPlugin slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-plugin title: Deprecated API usage by plugin description: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by. -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/deprecations_by_team.mdx b/api_docs/deprecations_by_team.mdx index 3027321eb62453..8545316f77c0fe 100644 --- a/api_docs/deprecations_by_team.mdx +++ b/api_docs/deprecations_by_team.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsDueByTeam slug: /kibana-dev-docs/api-meta/deprecations-due-by-team title: Deprecated APIs due to be removed, by team description: Lists the teams that are referencing deprecated APIs with a remove by date. -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/dev_tools.mdx b/api_docs/dev_tools.mdx index 7152c3dbc6e48f..334a2c08e23c39 100644 --- a/api_docs/dev_tools.mdx +++ b/api_docs/dev_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/devTools title: "devTools" image: https://source.unsplash.com/400x175/?github description: API docs for the devTools plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'devTools'] --- import devToolsObj from './dev_tools.devdocs.json'; diff --git a/api_docs/discover.mdx b/api_docs/discover.mdx index 1964aab8a60e72..6eb89f79f48077 100644 --- a/api_docs/discover.mdx +++ b/api_docs/discover.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discover title: "discover" image: https://source.unsplash.com/400x175/?github description: API docs for the discover plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discover'] --- import discoverObj from './discover.devdocs.json'; diff --git a/api_docs/discover_enhanced.mdx b/api_docs/discover_enhanced.mdx index 5811b914930dfe..3ddbd42c2bc732 100644 --- a/api_docs/discover_enhanced.mdx +++ b/api_docs/discover_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discoverEnhanced title: "discoverEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the discoverEnhanced plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discoverEnhanced'] --- import discoverEnhancedObj from './discover_enhanced.devdocs.json'; diff --git a/api_docs/embeddable.mdx b/api_docs/embeddable.mdx index 70caf3a3423d25..362609d3d6d49c 100644 --- a/api_docs/embeddable.mdx +++ b/api_docs/embeddable.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/embeddable title: "embeddable" image: https://source.unsplash.com/400x175/?github description: API docs for the embeddable plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddable'] --- import embeddableObj from './embeddable.devdocs.json'; diff --git a/api_docs/embeddable_enhanced.mdx b/api_docs/embeddable_enhanced.mdx index 96d0b7e56b5482..58bb7cbddd42b5 100644 --- a/api_docs/embeddable_enhanced.mdx +++ b/api_docs/embeddable_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/embeddableEnhanced title: "embeddableEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the embeddableEnhanced plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddableEnhanced'] --- import embeddableEnhancedObj from './embeddable_enhanced.devdocs.json'; diff --git a/api_docs/encrypted_saved_objects.mdx b/api_docs/encrypted_saved_objects.mdx index 3b1f766d5d43fc..002dd9eb271396 100644 --- a/api_docs/encrypted_saved_objects.mdx +++ b/api_docs/encrypted_saved_objects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/encryptedSavedObjects title: "encryptedSavedObjects" image: https://source.unsplash.com/400x175/?github description: API docs for the encryptedSavedObjects plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'encryptedSavedObjects'] --- import encryptedSavedObjectsObj from './encrypted_saved_objects.devdocs.json'; diff --git a/api_docs/enterprise_search.mdx b/api_docs/enterprise_search.mdx index 322441b1ad8520..5a45b7486d4c96 100644 --- a/api_docs/enterprise_search.mdx +++ b/api_docs/enterprise_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/enterpriseSearch title: "enterpriseSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the enterpriseSearch plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'enterpriseSearch'] --- import enterpriseSearchObj from './enterprise_search.devdocs.json'; diff --git a/api_docs/es_ui_shared.mdx b/api_docs/es_ui_shared.mdx index d2b0950778bfe3..b3f3fc87bda00d 100644 --- a/api_docs/es_ui_shared.mdx +++ b/api_docs/es_ui_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/esUiShared title: "esUiShared" image: https://source.unsplash.com/400x175/?github description: API docs for the esUiShared plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'esUiShared'] --- import esUiSharedObj from './es_ui_shared.devdocs.json'; diff --git a/api_docs/event_annotation.devdocs.json b/api_docs/event_annotation.devdocs.json index debcba1bf65992..45ace5e5039e6d 100644 --- a/api_docs/event_annotation.devdocs.json +++ b/api_docs/event_annotation.devdocs.json @@ -58,6 +58,61 @@ "returnComment": [], "initialIsOpen": false }, + { + "parentPluginId": "eventAnnotation", + "id": "def-public.isQueryAnnotationConfig", + "type": "Function", + "tags": [], + "label": "isQueryAnnotationConfig", + "description": [], + "signature": [ + "(annotation?: ", + { + "pluginId": "eventAnnotation", + "scope": "common", + "docId": "kibEventAnnotationPluginApi", + "section": "def-common.EventAnnotationConfig", + "text": "EventAnnotationConfig" + }, + " | undefined) => annotation is ", + { + "pluginId": "eventAnnotation", + "scope": "common", + "docId": "kibEventAnnotationPluginApi", + "section": "def-common.QueryPointEventAnnotationConfig", + "text": "QueryPointEventAnnotationConfig" + } + ], + "path": "src/plugins/event_annotation/public/event_annotation_service/helpers.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "eventAnnotation", + "id": "def-public.isQueryAnnotationConfig.$1", + "type": "CompoundType", + "tags": [], + "label": "annotation", + "description": [], + "signature": [ + { + "pluginId": "eventAnnotation", + "scope": "common", + "docId": "kibEventAnnotationPluginApi", + "section": "def-common.EventAnnotationConfig", + "text": "EventAnnotationConfig" + }, + " | undefined" + ], + "path": "src/plugins/event_annotation/public/event_annotation_service/helpers.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "eventAnnotation", "id": "def-public.isRangeAnnotationConfig", @@ -142,14 +197,15 @@ "section": "def-common.EventAnnotationConfig", "text": "EventAnnotationConfig" }, - ") => ", + "[]) => ", { "pluginId": "expressions", "scope": "common", "docId": "kibExpressionsPluginApi", "section": "def-common.ExpressionAstExpression", "text": "ExpressionAstExpression" - } + }, + "[]" ], "path": "src/plugins/event_annotation/public/event_annotation_service/types.ts", "deprecated": false, @@ -158,7 +214,7 @@ { "parentPluginId": "eventAnnotation", "id": "def-public.EventAnnotationServiceType.toExpression.$1", - "type": "CompoundType", + "type": "Array", "tags": [], "label": "props", "description": [], @@ -169,7 +225,8 @@ "docId": "kibEventAnnotationPluginApi", "section": "def-common.EventAnnotationConfig", "text": "EventAnnotationConfig" - } + }, + "[]" ], "path": "src/plugins/event_annotation/public/event_annotation_service/types.ts", "deprecated": false, @@ -178,6 +235,84 @@ } ], "returnComment": [] + }, + { + "parentPluginId": "eventAnnotation", + "id": "def-public.EventAnnotationServiceType.toFetchExpression", + "type": "Function", + "tags": [], + "label": "toFetchExpression", + "description": [], + "signature": [ + "(props: { interval: string; groups: ", + { + "pluginId": "eventAnnotation", + "scope": "common", + "docId": "kibEventAnnotationPluginApi", + "section": "def-common.EventAnnotationGroupConfig", + "text": "EventAnnotationGroupConfig" + }, + "[]; }) => ", + { + "pluginId": "expressions", + "scope": "common", + "docId": "kibExpressionsPluginApi", + "section": "def-common.ExpressionAstExpression", + "text": "ExpressionAstExpression" + }, + "[]" + ], + "path": "src/plugins/event_annotation/public/event_annotation_service/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "eventAnnotation", + "id": "def-public.EventAnnotationServiceType.toFetchExpression.$1", + "type": "Object", + "tags": [], + "label": "props", + "description": [], + "path": "src/plugins/event_annotation/public/event_annotation_service/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "eventAnnotation", + "id": "def-public.EventAnnotationServiceType.toFetchExpression.$1.interval", + "type": "string", + "tags": [], + "label": "interval", + "description": [], + "path": "src/plugins/event_annotation/public/event_annotation_service/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "eventAnnotation", + "id": "def-public.EventAnnotationServiceType.toFetchExpression.$1.groups", + "type": "Array", + "tags": [], + "label": "groups", + "description": [], + "signature": [ + { + "pluginId": "eventAnnotation", + "scope": "common", + "docId": "kibEventAnnotationPluginApi", + "section": "def-common.EventAnnotationGroupConfig", + "text": "EventAnnotationGroupConfig" + }, + "[]" + ], + "path": "src/plugins/event_annotation/public/event_annotation_service/types.ts", + "deprecated": false, + "trackAdoption": false + } + ] + } + ], + "returnComment": [] } ], "initialIsOpen": false @@ -375,6 +510,52 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "eventAnnotation", + "id": "def-common.EventAnnotationGroupConfig", + "type": "Interface", + "tags": [], + "label": "EventAnnotationGroupConfig", + "description": [], + "path": "src/plugins/event_annotation/common/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "eventAnnotation", + "id": "def-common.EventAnnotationGroupConfig.annotations", + "type": "Array", + "tags": [], + "label": "annotations", + "description": [], + "signature": [ + { + "pluginId": "eventAnnotation", + "scope": "common", + "docId": "kibEventAnnotationPluginApi", + "section": "def-common.EventAnnotationConfig", + "text": "EventAnnotationConfig" + }, + "[]" + ], + "path": "src/plugins/event_annotation/common/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "eventAnnotation", + "id": "def-common.EventAnnotationGroupConfig.indexPatternId", + "type": "string", + "tags": [], + "label": "indexPatternId", + "description": [], + "path": "src/plugins/event_annotation/common/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "eventAnnotation", "id": "def-common.FetchEventAnnotationsArgs", @@ -538,8 +719,17 @@ "label": "ManualPointEventAnnotationArgs", "description": [], "signature": [ - "{ id: string; time: string; } & ", - "PointStyleProps" + "{ id: string; time: string; } & StyleSharedProps & { icon?: ", + { + "pluginId": "eventAnnotation", + "scope": "common", + "docId": "kibEventAnnotationPluginApi", + "section": "def-common.AvailableAnnotationIcon", + "text": "AvailableAnnotationIcon" + }, + " | undefined; lineWidth?: number | undefined; lineStyle?: ", + "LineStyle", + " | undefined; textVisibility?: boolean | undefined; }" ], "path": "src/plugins/event_annotation/common/manual_event_annotation/types.ts", "deprecated": false, @@ -554,9 +744,17 @@ "label": "ManualPointEventAnnotationOutput", "description": [], "signature": [ - "{ id: string; time: string; } & ", - "PointStyleProps", - " & { type: \"manual_point_event_annotation\"; }" + "{ id: string; time: string; } & StyleSharedProps & { icon?: ", + { + "pluginId": "eventAnnotation", + "scope": "common", + "docId": "kibEventAnnotationPluginApi", + "section": "def-common.AvailableAnnotationIcon", + "text": "AvailableAnnotationIcon" + }, + " | undefined; lineWidth?: number | undefined; lineStyle?: ", + "LineStyle", + " | undefined; textVisibility?: boolean | undefined; } & { type: \"manual_point_event_annotation\"; }" ], "path": "src/plugins/event_annotation/common/manual_event_annotation/types.ts", "deprecated": false, @@ -565,14 +763,13 @@ }, { "parentPluginId": "eventAnnotation", - "id": "def-common.ManualPointEventAnnotationRow", + "id": "def-common.ManualRangeEventAnnotationArgs", "type": "Type", "tags": [], - "label": "ManualPointEventAnnotationRow", + "label": "ManualRangeEventAnnotationArgs", "description": [], "signature": [ - "{ id: string; time: string; type: \"point\"; timebucket: string; skippedCount?: string | undefined; } & ", - "PointStyleProps" + "{ id: string; time: string; endTime: string; } & StyleSharedProps & { outside?: boolean | undefined; }" ], "path": "src/plugins/event_annotation/common/manual_event_annotation/types.ts", "deprecated": false, @@ -581,14 +778,13 @@ }, { "parentPluginId": "eventAnnotation", - "id": "def-common.ManualRangeEventAnnotationArgs", + "id": "def-common.ManualRangeEventAnnotationOutput", "type": "Type", "tags": [], - "label": "ManualRangeEventAnnotationArgs", + "label": "ManualRangeEventAnnotationOutput", "description": [], "signature": [ - "{ id: string; time: string; endTime: string; } & ", - "RangeStyleProps" + "{ id: string; time: string; endTime: string; } & StyleSharedProps & { outside?: boolean | undefined; } & { type: \"manual_range_event_annotation\"; }" ], "path": "src/plugins/event_annotation/common/manual_event_annotation/types.ts", "deprecated": false, @@ -597,15 +793,13 @@ }, { "parentPluginId": "eventAnnotation", - "id": "def-common.ManualRangeEventAnnotationOutput", + "id": "def-common.ManualRangeEventAnnotationRow", "type": "Type", "tags": [], - "label": "ManualRangeEventAnnotationOutput", + "label": "ManualRangeEventAnnotationRow", "description": [], "signature": [ - "{ id: string; time: string; endTime: string; } & ", - "RangeStyleProps", - " & { type: \"manual_range_event_annotation\"; }" + "{ id: string; time: string; endTime: string; type: \"range\"; } & StyleSharedProps & { outside?: boolean | undefined; }" ], "path": "src/plugins/event_annotation/common/manual_event_annotation/types.ts", "deprecated": false, @@ -614,14 +808,23 @@ }, { "parentPluginId": "eventAnnotation", - "id": "def-common.ManualRangeEventAnnotationRow", + "id": "def-common.PointEventAnnotationRow", "type": "Type", "tags": [], - "label": "ManualRangeEventAnnotationRow", + "label": "PointEventAnnotationRow", "description": [], "signature": [ - "{ id: string; time: string; endTime: string; type: \"range\"; } & ", - "RangeStyleProps" + "{ id: string; time: string; type: \"point\"; timebucket: string; skippedCount?: number | undefined; } & StyleSharedProps & { icon?: ", + { + "pluginId": "eventAnnotation", + "scope": "common", + "docId": "kibEventAnnotationPluginApi", + "section": "def-common.AvailableAnnotationIcon", + "text": "AvailableAnnotationIcon" + }, + " | undefined; lineWidth?: number | undefined; lineStyle?: ", + "LineStyle", + " | undefined; textVisibility?: boolean | undefined; } & Record" ], "path": "src/plugins/event_annotation/common/manual_event_annotation/types.ts", "deprecated": false, @@ -636,8 +839,17 @@ "label": "PointInTimeEventAnnotationConfig", "description": [], "signature": [ - "{ id: string; key: { type: \"point_in_time\"; timestamp: string; }; } & ", - "PointStyleProps" + "{ id: string; type: \"manual\"; key: { type: \"point_in_time\"; timestamp: string; }; } & StyleSharedProps & { icon?: ", + { + "pluginId": "eventAnnotation", + "scope": "common", + "docId": "kibEventAnnotationPluginApi", + "section": "def-common.AvailableAnnotationIcon", + "text": "AvailableAnnotationIcon" + }, + " | undefined; lineWidth?: number | undefined; lineStyle?: ", + "LineStyle", + " | undefined; textVisibility?: boolean | undefined; }" ], "path": "src/plugins/event_annotation/common/types.ts", "deprecated": false, @@ -660,8 +872,17 @@ "section": "def-common.KibanaQueryOutput", "text": "KibanaQueryOutput" }, - "; timeField: string; extraFields?: string[] | undefined; textField?: string | undefined; } & ", - "PointStyleProps" + "; timeField?: string | undefined; extraFields?: string[] | undefined; textField?: string | undefined; } & StyleSharedProps & { icon?: ", + { + "pluginId": "eventAnnotation", + "scope": "common", + "docId": "kibEventAnnotationPluginApi", + "section": "def-common.AvailableAnnotationIcon", + "text": "AvailableAnnotationIcon" + }, + " | undefined; lineWidth?: number | undefined; lineStyle?: ", + "LineStyle", + " | undefined; textVisibility?: boolean | undefined; }" ], "path": "src/plugins/event_annotation/common/query_point_event_annotation/types.ts", "deprecated": false, @@ -676,7 +897,7 @@ "label": "QueryPointEventAnnotationConfig", "description": [], "signature": [ - "{ id: string; filter: ", + "{ id: string; type: \"query\"; filter: ", { "pluginId": "data", "scope": "common", @@ -684,8 +905,17 @@ "section": "def-common.KibanaQueryOutput", "text": "KibanaQueryOutput" }, - "; timeField: string; textField: string; extraFields?: string[] | undefined; key: { type: \"point_in_time\"; }; } & ", - "PointStyleProps" + "; timeField?: string | undefined; textField?: string | undefined; extraFields?: string[] | undefined; key: { type: \"point_in_time\"; }; } & StyleSharedProps & { icon?: ", + { + "pluginId": "eventAnnotation", + "scope": "common", + "docId": "kibEventAnnotationPluginApi", + "section": "def-common.AvailableAnnotationIcon", + "text": "AvailableAnnotationIcon" + }, + " | undefined; lineWidth?: number | undefined; lineStyle?: ", + "LineStyle", + " | undefined; textVisibility?: boolean | undefined; }" ], "path": "src/plugins/event_annotation/common/types.ts", "deprecated": false, @@ -708,9 +938,17 @@ "section": "def-common.KibanaQueryOutput", "text": "KibanaQueryOutput" }, - "; timeField: string; extraFields?: string[] | undefined; textField?: string | undefined; } & ", - "PointStyleProps", - " & { type: \"query_point_event_annotation\"; }" + "; timeField?: string | undefined; extraFields?: string[] | undefined; textField?: string | undefined; } & StyleSharedProps & { icon?: ", + { + "pluginId": "eventAnnotation", + "scope": "common", + "docId": "kibEventAnnotationPluginApi", + "section": "def-common.AvailableAnnotationIcon", + "text": "AvailableAnnotationIcon" + }, + " | undefined; lineWidth?: number | undefined; lineStyle?: ", + "LineStyle", + " | undefined; textVisibility?: boolean | undefined; } & { type: \"query_point_event_annotation\"; }" ], "path": "src/plugins/event_annotation/common/query_point_event_annotation/types.ts", "deprecated": false, @@ -725,8 +963,7 @@ "label": "RangeEventAnnotationConfig", "description": [], "signature": [ - "{ id: string; key: { type: \"range\"; timestamp: string; endTimestamp: string; }; } & ", - "RangeStyleProps" + "{ type: \"manual\"; id: string; key: { type: \"range\"; timestamp: string; endTimestamp: string; }; } & StyleSharedProps & { outside?: boolean | undefined; }" ], "path": "src/plugins/event_annotation/common/types.ts", "deprecated": false, @@ -1240,7 +1477,7 @@ "section": "def-common.ManualPointEventAnnotationArgs", "text": "ManualPointEventAnnotationArgs" }, - ") => { id: string; time: string; label: string; color?: string | undefined; icon?: ", + ") => { id: string; time: string; label: string; color?: string | undefined; isHidden?: boolean | undefined; icon?: ", { "pluginId": "eventAnnotation", "scope": "common", @@ -1250,7 +1487,7 @@ }, " | undefined; lineWidth?: number | undefined; lineStyle?: ", "LineStyle", - " | undefined; textVisibility?: boolean | undefined; isHidden?: boolean | undefined; type: \"manual_point_event_annotation\"; }" + " | undefined; textVisibility?: boolean | undefined; type: \"manual_point_event_annotation\"; }" ], "path": "src/plugins/event_annotation/common/manual_event_annotation/index.ts", "deprecated": false, @@ -1279,8 +1516,17 @@ "label": "args", "description": [], "signature": [ - "{ id: string; time: string; } & ", - "PointStyleProps" + "{ id: string; time: string; } & StyleSharedProps & { icon?: ", + { + "pluginId": "eventAnnotation", + "scope": "common", + "docId": "kibEventAnnotationPluginApi", + "section": "def-common.AvailableAnnotationIcon", + "text": "AvailableAnnotationIcon" + }, + " | undefined; lineWidth?: number | undefined; lineStyle?: ", + "LineStyle", + " | undefined; textVisibility?: boolean | undefined; }" ], "path": "src/plugins/event_annotation/common/manual_event_annotation/index.ts", "deprecated": false, @@ -1706,7 +1952,7 @@ "section": "def-common.ManualRangeEventAnnotationArgs", "text": "ManualRangeEventAnnotationArgs" }, - ") => { id: string; time: string; endTime: string; label: string; color?: string | undefined; outside?: boolean | undefined; isHidden?: boolean | undefined; type: \"manual_range_event_annotation\"; }" + ") => { id: string; time: string; endTime: string; label: string; color?: string | undefined; isHidden?: boolean | undefined; outside?: boolean | undefined; type: \"manual_range_event_annotation\"; }" ], "path": "src/plugins/event_annotation/common/manual_event_annotation/index.ts", "deprecated": false, @@ -1735,8 +1981,7 @@ "label": "args", "description": [], "signature": [ - "{ id: string; time: string; endTime: string; } & ", - "RangeStyleProps" + "{ id: string; time: string; endTime: string; } & StyleSharedProps & { outside?: boolean | undefined; }" ], "path": "src/plugins/event_annotation/common/manual_event_annotation/index.ts", "deprecated": false, @@ -1923,20 +2168,6 @@ "path": "src/plugins/event_annotation/common/query_point_event_annotation/index.ts", "deprecated": false, "trackAdoption": false - }, - { - "parentPluginId": "eventAnnotation", - "id": "def-common.queryPointEventAnnotation.args.filter.required", - "type": "boolean", - "tags": [], - "label": "required", - "description": [], - "signature": [ - "true" - ], - "path": "src/plugins/event_annotation/common/query_point_event_annotation/index.ts", - "deprecated": false, - "trackAdoption": false } ] }, @@ -2003,20 +2234,6 @@ "deprecated": false, "trackAdoption": false, "children": [ - { - "parentPluginId": "eventAnnotation", - "id": "def-common.queryPointEventAnnotation.args.timeField.required", - "type": "boolean", - "tags": [], - "label": "required", - "description": [], - "signature": [ - "true" - ], - "path": "src/plugins/event_annotation/common/query_point_event_annotation/index.ts", - "deprecated": false, - "trackAdoption": false - }, { "parentPluginId": "eventAnnotation", "id": "def-common.queryPointEventAnnotation.args.timeField.types", @@ -2416,7 +2633,7 @@ "section": "def-common.KibanaQueryOutput", "text": "KibanaQueryOutput" }, - "; timeField: string; extraFields?: string[] | undefined; textField?: string | undefined; label: string; color?: string | undefined; icon?: ", + "; timeField?: string | undefined; extraFields?: string[] | undefined; textField?: string | undefined; label: string; color?: string | undefined; isHidden?: boolean | undefined; icon?: ", { "pluginId": "eventAnnotation", "scope": "common", @@ -2426,7 +2643,7 @@ }, " | undefined; lineWidth?: number | undefined; lineStyle?: ", "LineStyle", - " | undefined; textVisibility?: boolean | undefined; isHidden?: boolean | undefined; type: \"query_point_event_annotation\"; }" + " | undefined; textVisibility?: boolean | undefined; type: \"query_point_event_annotation\"; }" ], "path": "src/plugins/event_annotation/common/query_point_event_annotation/index.ts", "deprecated": false, @@ -2463,8 +2680,17 @@ "section": "def-common.KibanaQueryOutput", "text": "KibanaQueryOutput" }, - "; timeField: string; extraFields?: string[] | undefined; textField?: string | undefined; } & ", - "PointStyleProps" + "; timeField?: string | undefined; extraFields?: string[] | undefined; textField?: string | undefined; } & StyleSharedProps & { icon?: ", + { + "pluginId": "eventAnnotation", + "scope": "common", + "docId": "kibEventAnnotationPluginApi", + "section": "def-common.AvailableAnnotationIcon", + "text": "AvailableAnnotationIcon" + }, + " | undefined; lineWidth?: number | undefined; lineStyle?: ", + "LineStyle", + " | undefined; textVisibility?: boolean | undefined; }" ], "path": "src/plugins/event_annotation/common/query_point_event_annotation/index.ts", "deprecated": false, diff --git a/api_docs/event_annotation.mdx b/api_docs/event_annotation.mdx index 0b17864905a2e1..0161dd80da0d72 100644 --- a/api_docs/event_annotation.mdx +++ b/api_docs/event_annotation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventAnnotation title: "eventAnnotation" image: https://source.unsplash.com/400x175/?github description: API docs for the eventAnnotation plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventAnnotation'] --- import eventAnnotationObj from './event_annotation.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 163 | 0 | 163 | 5 | +| 170 | 0 | 170 | 3 | ## Client diff --git a/api_docs/event_log.mdx b/api_docs/event_log.mdx index cf1ddf2891d12e..3867ef968cdda5 100644 --- a/api_docs/event_log.mdx +++ b/api_docs/event_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventLog title: "eventLog" image: https://source.unsplash.com/400x175/?github description: API docs for the eventLog plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventLog'] --- import eventLogObj from './event_log.devdocs.json'; diff --git a/api_docs/expression_error.mdx b/api_docs/expression_error.mdx index 06faf9fb410ece..f8a6757785b98f 100644 --- a/api_docs/expression_error.mdx +++ b/api_docs/expression_error.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionError title: "expressionError" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionError plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionError'] --- import expressionErrorObj from './expression_error.devdocs.json'; diff --git a/api_docs/expression_gauge.mdx b/api_docs/expression_gauge.mdx index 20e186f5644ce6..9c151c832439fe 100644 --- a/api_docs/expression_gauge.mdx +++ b/api_docs/expression_gauge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionGauge title: "expressionGauge" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionGauge plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionGauge'] --- import expressionGaugeObj from './expression_gauge.devdocs.json'; diff --git a/api_docs/expression_heatmap.mdx b/api_docs/expression_heatmap.mdx index 404f0688b7d1d3..18e588eda03225 100644 --- a/api_docs/expression_heatmap.mdx +++ b/api_docs/expression_heatmap.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionHeatmap title: "expressionHeatmap" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionHeatmap plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionHeatmap'] --- import expressionHeatmapObj from './expression_heatmap.devdocs.json'; diff --git a/api_docs/expression_image.mdx b/api_docs/expression_image.mdx index 4fd5a55f50085b..7c7fcf1e51a85e 100644 --- a/api_docs/expression_image.mdx +++ b/api_docs/expression_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionImage title: "expressionImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionImage plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionImage'] --- import expressionImageObj from './expression_image.devdocs.json'; diff --git a/api_docs/expression_legacy_metric_vis.mdx b/api_docs/expression_legacy_metric_vis.mdx index d7358588b94c06..227caffdd86aef 100644 --- a/api_docs/expression_legacy_metric_vis.mdx +++ b/api_docs/expression_legacy_metric_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionLegacyMetricVis title: "expressionLegacyMetricVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionLegacyMetricVis plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionLegacyMetricVis'] --- import expressionLegacyMetricVisObj from './expression_legacy_metric_vis.devdocs.json'; diff --git a/api_docs/expression_metric.mdx b/api_docs/expression_metric.mdx index 75b2eb2c6f778d..73127734fb39d0 100644 --- a/api_docs/expression_metric.mdx +++ b/api_docs/expression_metric.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionMetric title: "expressionMetric" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionMetric plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionMetric'] --- import expressionMetricObj from './expression_metric.devdocs.json'; diff --git a/api_docs/expression_metric_vis.mdx b/api_docs/expression_metric_vis.mdx index 63c77f4efce129..ee91044586ad45 100644 --- a/api_docs/expression_metric_vis.mdx +++ b/api_docs/expression_metric_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionMetricVis title: "expressionMetricVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionMetricVis plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionMetricVis'] --- import expressionMetricVisObj from './expression_metric_vis.devdocs.json'; diff --git a/api_docs/expression_partition_vis.mdx b/api_docs/expression_partition_vis.mdx index 99a7e75a8a1deb..30188432c4589b 100644 --- a/api_docs/expression_partition_vis.mdx +++ b/api_docs/expression_partition_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionPartitionVis title: "expressionPartitionVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionPartitionVis plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionPartitionVis'] --- import expressionPartitionVisObj from './expression_partition_vis.devdocs.json'; diff --git a/api_docs/expression_repeat_image.mdx b/api_docs/expression_repeat_image.mdx index 02146ab3b4dd60..abbd5e0f52ab51 100644 --- a/api_docs/expression_repeat_image.mdx +++ b/api_docs/expression_repeat_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionRepeatImage title: "expressionRepeatImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionRepeatImage plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionRepeatImage'] --- import expressionRepeatImageObj from './expression_repeat_image.devdocs.json'; diff --git a/api_docs/expression_reveal_image.mdx b/api_docs/expression_reveal_image.mdx index c992509c3b90a7..ae05b346c5294f 100644 --- a/api_docs/expression_reveal_image.mdx +++ b/api_docs/expression_reveal_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionRevealImage title: "expressionRevealImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionRevealImage plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionRevealImage'] --- import expressionRevealImageObj from './expression_reveal_image.devdocs.json'; diff --git a/api_docs/expression_shape.mdx b/api_docs/expression_shape.mdx index 157d67a02113cb..3df0f71990ee19 100644 --- a/api_docs/expression_shape.mdx +++ b/api_docs/expression_shape.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionShape title: "expressionShape" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionShape plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionShape'] --- import expressionShapeObj from './expression_shape.devdocs.json'; diff --git a/api_docs/expression_tagcloud.mdx b/api_docs/expression_tagcloud.mdx index b43acd78e213ae..312da9ec73cca8 100644 --- a/api_docs/expression_tagcloud.mdx +++ b/api_docs/expression_tagcloud.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionTagcloud title: "expressionTagcloud" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionTagcloud plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionTagcloud'] --- import expressionTagcloudObj from './expression_tagcloud.devdocs.json'; diff --git a/api_docs/expression_x_y.devdocs.json b/api_docs/expression_x_y.devdocs.json index 9f270c01df4331..86ab5bf0357523 100644 --- a/api_docs/expression_x_y.devdocs.json +++ b/api_docs/expression_x_y.devdocs.json @@ -426,92 +426,6 @@ ], "initialIsOpen": false }, - { - "parentPluginId": "expressionXY", - "id": "def-common.CollectiveConfig", - "type": "Interface", - "tags": [], - "label": "CollectiveConfig", - "description": [], - "signature": [ - { - "pluginId": "expressionXY", - "scope": "common", - "docId": "kibExpressionXYPluginApi", - "section": "def-common.CollectiveConfig", - "text": "CollectiveConfig" - }, - " extends Omit<", - { - "pluginId": "eventAnnotation", - "scope": "common", - "docId": "kibEventAnnotationPluginApi", - "section": "def-common.ManualPointEventAnnotationArgs", - "text": "ManualPointEventAnnotationArgs" - }, - ", \"icon\">" - ], - "path": "src/plugins/chart_expressions/expression_xy/common/types/expression_renderers.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "expressionXY", - "id": "def-common.CollectiveConfig.timebucket", - "type": "number", - "tags": [], - "label": "timebucket", - "description": [], - "path": "src/plugins/chart_expressions/expression_xy/common/types/expression_renderers.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "expressionXY", - "id": "def-common.CollectiveConfig.position", - "type": "string", - "tags": [], - "label": "position", - "description": [], - "signature": [ - "\"bottom\"" - ], - "path": "src/plugins/chart_expressions/expression_xy/common/types/expression_renderers.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "expressionXY", - "id": "def-common.CollectiveConfig.icon", - "type": "string", - "tags": [], - "label": "icon", - "description": [], - "signature": [ - "string | undefined" - ], - "path": "src/plugins/chart_expressions/expression_xy/common/types/expression_renderers.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "expressionXY", - "id": "def-common.CollectiveConfig.customTooltipDetails", - "type": "Function", - "tags": [], - "label": "customTooltipDetails", - "description": [], - "signature": [ - "AnnotationTooltipFormatter", - " | undefined" - ], - "path": "src/plugins/chart_expressions/expression_xy/common/types/expression_renderers.ts", - "deprecated": false, - "trackAdoption": false - } - ], - "initialIsOpen": false - }, { "parentPluginId": "expressionXY", "id": "def-common.DataDecorationConfig", @@ -1058,6 +972,119 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "expressionXY", + "id": "def-common.MergedAnnotation", + "type": "Interface", + "tags": [], + "label": "MergedAnnotation", + "description": [], + "signature": [ + { + "pluginId": "expressionXY", + "scope": "common", + "docId": "kibExpressionXYPluginApi", + "section": "def-common.MergedAnnotation", + "text": "MergedAnnotation" + }, + " extends Omit<", + { + "pluginId": "eventAnnotation", + "scope": "common", + "docId": "kibEventAnnotationPluginApi", + "section": "def-common.ManualPointEventAnnotationArgs", + "text": "ManualPointEventAnnotationArgs" + }, + ", \"icon\">" + ], + "path": "src/plugins/chart_expressions/expression_xy/common/types/expression_renderers.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "expressionXY", + "id": "def-common.MergedAnnotation.timebucket", + "type": "number", + "tags": [], + "label": "timebucket", + "description": [], + "path": "src/plugins/chart_expressions/expression_xy/common/types/expression_renderers.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "expressionXY", + "id": "def-common.MergedAnnotation.position", + "type": "string", + "tags": [], + "label": "position", + "description": [], + "signature": [ + "\"bottom\"" + ], + "path": "src/plugins/chart_expressions/expression_xy/common/types/expression_renderers.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "expressionXY", + "id": "def-common.MergedAnnotation.icon", + "type": "string", + "tags": [], + "label": "icon", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/chart_expressions/expression_xy/common/types/expression_renderers.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "expressionXY", + "id": "def-common.MergedAnnotation.customTooltipDetails", + "type": "Function", + "tags": [], + "label": "customTooltipDetails", + "description": [], + "signature": [ + "(details?: string | undefined) => JSX.Element | null" + ], + "path": "src/plugins/chart_expressions/expression_xy/common/types/expression_renderers.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "expressionXY", + "id": "def-common.MergedAnnotation.customTooltipDetails.$1", + "type": "string", + "tags": [], + "label": "details", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "node_modules/@elastic/charts/dist/chart_types/xy_chart/annotations/types.d.ts", + "deprecated": false, + "trackAdoption": false + } + ] + }, + { + "parentPluginId": "expressionXY", + "id": "def-common.MergedAnnotation.isGrouped", + "type": "boolean", + "tags": [], + "label": "isGrouped", + "description": [], + "path": "src/plugins/chart_expressions/expression_xy/common/types/expression_renderers.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "expressionXY", "id": "def-common.ReferenceLineDecorationConfig", @@ -1479,21 +1506,6 @@ "deprecated": false, "trackAdoption": false }, - { - "parentPluginId": "expressionXY", - "id": "def-common.XYArgs.annotationLayers", - "type": "Array", - "tags": [], - "label": "annotationLayers", - "description": [], - "signature": [ - "AnnotationLayerConfigResult", - "[]" - ], - "path": "src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts", - "deprecated": false, - "trackAdoption": false - }, { "parentPluginId": "expressionXY", "id": "def-common.XYArgs.fittingFunction", @@ -2587,9 +2599,7 @@ "docId": "kibExpressionXYPluginApi", "section": "def-common.ReferenceLineLayerConfigResult", "text": "ReferenceLineLayerConfigResult" - }, - " | ", - "ExtendedAnnotationLayerConfigResult" + } ], "path": "src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts", "deprecated": false, @@ -2612,15 +2622,15 @@ "text": "DataLayerArgs" }, " | ", + "ReferenceLineArgs", + " | ", { "pluginId": "expressionXY", "scope": "common", "docId": "kibExpressionXYPluginApi", "section": "def-common.AnnotationLayerArgs", "text": "AnnotationLayerArgs" - }, - " | ", - "ReferenceLineArgs" + } ], "path": "src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts", "deprecated": false, diff --git a/api_docs/expression_x_y.mdx b/api_docs/expression_x_y.mdx index f5aa37c47d8bd6..9720c8b749c920 100644 --- a/api_docs/expression_x_y.mdx +++ b/api_docs/expression_x_y.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionXY title: "expressionXY" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionXY plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionXY'] --- import expressionXYObj from './expression_x_y.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 152 | 0 | 142 | 11 | +| 153 | 0 | 142 | 9 | ## Client diff --git a/api_docs/expressions.mdx b/api_docs/expressions.mdx index e170014e3ffc71..3bc004877bf6d4 100644 --- a/api_docs/expressions.mdx +++ b/api_docs/expressions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressions title: "expressions" image: https://source.unsplash.com/400x175/?github description: API docs for the expressions plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressions'] --- import expressionsObj from './expressions.devdocs.json'; diff --git a/api_docs/features.mdx b/api_docs/features.mdx index 1dc8dd28ad1000..d3bfbec1eafaa5 100644 --- a/api_docs/features.mdx +++ b/api_docs/features.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/features title: "features" image: https://source.unsplash.com/400x175/?github description: API docs for the features plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'features'] --- import featuresObj from './features.devdocs.json'; diff --git a/api_docs/field_formats.mdx b/api_docs/field_formats.mdx index cca2af12379c4c..47ac9e94ccb6fe 100644 --- a/api_docs/field_formats.mdx +++ b/api_docs/field_formats.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fieldFormats title: "fieldFormats" image: https://source.unsplash.com/400x175/?github description: API docs for the fieldFormats plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fieldFormats'] --- import fieldFormatsObj from './field_formats.devdocs.json'; diff --git a/api_docs/file_upload.mdx b/api_docs/file_upload.mdx index 7d7005d146d321..00ef1834df39bb 100644 --- a/api_docs/file_upload.mdx +++ b/api_docs/file_upload.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fileUpload title: "fileUpload" image: https://source.unsplash.com/400x175/?github description: API docs for the fileUpload plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fileUpload'] --- import fileUploadObj from './file_upload.devdocs.json'; diff --git a/api_docs/files.mdx b/api_docs/files.mdx index 6a97b8d21b89be..b94441baeff075 100644 --- a/api_docs/files.mdx +++ b/api_docs/files.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/files title: "files" image: https://source.unsplash.com/400x175/?github description: API docs for the files plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'files'] --- import filesObj from './files.devdocs.json'; diff --git a/api_docs/fleet.devdocs.json b/api_docs/fleet.devdocs.json index 0600244c7d5919..267549af758387 100644 --- a/api_docs/fleet.devdocs.json +++ b/api_docs/fleet.devdocs.json @@ -8914,14 +8914,14 @@ { "parentPluginId": "fleet", "id": "def-common.FleetServerAgent.upgraded_at", - "type": "CompoundType", + "type": "string", "tags": [], "label": "upgraded_at", "description": [ "\nDate/time the Elastic Agent was last upgraded" ], "signature": [ - "string | null | undefined" + "string | undefined" ], "path": "x-pack/plugins/fleet/common/types/models/agent.ts", "deprecated": false, @@ -8943,6 +8943,22 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "fleet", + "id": "def-common.FleetServerAgent.upgrade_status", + "type": "CompoundType", + "tags": [], + "label": "upgrade_status", + "description": [ + "\nUpgrade status" + ], + "signature": [ + "\"completed\" | \"started\" | undefined" + ], + "path": "x-pack/plugins/fleet/common/types/models/agent.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "fleet", "id": "def-common.FleetServerAgent.access_api_key_id", @@ -9111,7 +9127,7 @@ "tags": [], "label": "last_checkin_status", "description": [ - "\nLst checkin status" + "\nLast checkin status" ], "signature": [ "\"error\" | \"online\" | \"updating\" | \"degraded\" | undefined" diff --git a/api_docs/fleet.mdx b/api_docs/fleet.mdx index 7c71b34ed84e57..212a823589def5 100644 --- a/api_docs/fleet.mdx +++ b/api_docs/fleet.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fleet title: "fleet" image: https://source.unsplash.com/400x175/?github description: API docs for the fleet plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fleet'] --- import fleetObj from './fleet.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Fleet](https://github.com/orgs/elastic/teams/fleet) for questions regar | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 969 | 3 | 873 | 10 | +| 970 | 3 | 873 | 10 | ## Client diff --git a/api_docs/global_search.mdx b/api_docs/global_search.mdx index b034c8b7cb9e00..151db33c2bbd07 100644 --- a/api_docs/global_search.mdx +++ b/api_docs/global_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/globalSearch title: "globalSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the globalSearch plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'globalSearch'] --- import globalSearchObj from './global_search.devdocs.json'; diff --git a/api_docs/home.mdx b/api_docs/home.mdx index 4c9eda5502b863..0633e4a8248504 100644 --- a/api_docs/home.mdx +++ b/api_docs/home.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/home title: "home" image: https://source.unsplash.com/400x175/?github description: API docs for the home plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'home'] --- import homeObj from './home.devdocs.json'; diff --git a/api_docs/index_lifecycle_management.mdx b/api_docs/index_lifecycle_management.mdx index f034d977a97fcb..7cd6a257eeca1a 100644 --- a/api_docs/index_lifecycle_management.mdx +++ b/api_docs/index_lifecycle_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/indexLifecycleManagement title: "indexLifecycleManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the indexLifecycleManagement plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexLifecycleManagement'] --- import indexLifecycleManagementObj from './index_lifecycle_management.devdocs.json'; diff --git a/api_docs/index_management.mdx b/api_docs/index_management.mdx index 15c82e01c6a325..b83bcf59070e4a 100644 --- a/api_docs/index_management.mdx +++ b/api_docs/index_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/indexManagement title: "indexManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the indexManagement plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexManagement'] --- import indexManagementObj from './index_management.devdocs.json'; diff --git a/api_docs/infra.mdx b/api_docs/infra.mdx index 5926c936d88648..05616b0cfadc4e 100644 --- a/api_docs/infra.mdx +++ b/api_docs/infra.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/infra title: "infra" image: https://source.unsplash.com/400x175/?github description: API docs for the infra plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'infra'] --- import infraObj from './infra.devdocs.json'; diff --git a/api_docs/inspector.mdx b/api_docs/inspector.mdx index 6935d2be13e2dd..8454800519cb03 100644 --- a/api_docs/inspector.mdx +++ b/api_docs/inspector.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/inspector title: "inspector" image: https://source.unsplash.com/400x175/?github description: API docs for the inspector plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'inspector'] --- import inspectorObj from './inspector.devdocs.json'; diff --git a/api_docs/interactive_setup.mdx b/api_docs/interactive_setup.mdx index 8f4d5abc9e06af..100b024c58ddf9 100644 --- a/api_docs/interactive_setup.mdx +++ b/api_docs/interactive_setup.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/interactiveSetup title: "interactiveSetup" image: https://source.unsplash.com/400x175/?github description: API docs for the interactiveSetup plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'interactiveSetup'] --- import interactiveSetupObj from './interactive_setup.devdocs.json'; diff --git a/api_docs/kbn_ace.mdx b/api_docs/kbn_ace.mdx index 121e38701329ca..4606d800cf22e9 100644 --- a/api_docs/kbn_ace.mdx +++ b/api_docs/kbn_ace.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ace title: "@kbn/ace" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ace plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ace'] --- import kbnAceObj from './kbn_ace.devdocs.json'; diff --git a/api_docs/kbn_aiops_components.mdx b/api_docs/kbn_aiops_components.mdx index 6d5933c4337e9e..765ff1f91971fd 100644 --- a/api_docs/kbn_aiops_components.mdx +++ b/api_docs/kbn_aiops_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-components title: "@kbn/aiops-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-components plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-components'] --- import kbnAiopsComponentsObj from './kbn_aiops_components.devdocs.json'; diff --git a/api_docs/kbn_aiops_utils.mdx b/api_docs/kbn_aiops_utils.mdx index 54ba172cc62202..4b51bc25be8909 100644 --- a/api_docs/kbn_aiops_utils.mdx +++ b/api_docs/kbn_aiops_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-utils title: "@kbn/aiops-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-utils plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-utils'] --- import kbnAiopsUtilsObj from './kbn_aiops_utils.devdocs.json'; diff --git a/api_docs/kbn_alerts.mdx b/api_docs/kbn_alerts.mdx index 2c6d1d0c39de07..d5a04ff5eee17e 100644 --- a/api_docs/kbn_alerts.mdx +++ b/api_docs/kbn_alerts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerts title: "@kbn/alerts" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerts plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts'] --- import kbnAlertsObj from './kbn_alerts.devdocs.json'; diff --git a/api_docs/kbn_analytics.mdx b/api_docs/kbn_analytics.mdx index 7ec9a3e17c0355..a99efc95e8c132 100644 --- a/api_docs/kbn_analytics.mdx +++ b/api_docs/kbn_analytics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics title: "@kbn/analytics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics'] --- import kbnAnalyticsObj from './kbn_analytics.devdocs.json'; diff --git a/api_docs/kbn_analytics_client.mdx b/api_docs/kbn_analytics_client.mdx index 9a511085c8190a..1fd92e71b327ac 100644 --- a/api_docs/kbn_analytics_client.mdx +++ b/api_docs/kbn_analytics_client.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-client title: "@kbn/analytics-client" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-client plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-client'] --- import kbnAnalyticsClientObj from './kbn_analytics_client.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx index ec0dee99a84708..4f9fac4a0b2ece 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-browser title: "@kbn/analytics-shippers-elastic-v3-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-browser plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-browser'] --- import kbnAnalyticsShippersElasticV3BrowserObj from './kbn_analytics_shippers_elastic_v3_browser.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx index 2e503510d978fa..ada937d1aa30eb 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-common title: "@kbn/analytics-shippers-elastic-v3-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-common plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-common'] --- import kbnAnalyticsShippersElasticV3CommonObj from './kbn_analytics_shippers_elastic_v3_common.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx index ae8f78c83ab2b4..360208b56403ba 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-server title: "@kbn/analytics-shippers-elastic-v3-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-server plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-server'] --- import kbnAnalyticsShippersElasticV3ServerObj from './kbn_analytics_shippers_elastic_v3_server.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_fullstory.mdx b/api_docs/kbn_analytics_shippers_fullstory.mdx index b9bd132b732444..995d23de7fcc71 100644 --- a/api_docs/kbn_analytics_shippers_fullstory.mdx +++ b/api_docs/kbn_analytics_shippers_fullstory.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-fullstory title: "@kbn/analytics-shippers-fullstory" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-fullstory plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-fullstory'] --- import kbnAnalyticsShippersFullstoryObj from './kbn_analytics_shippers_fullstory.devdocs.json'; diff --git a/api_docs/kbn_apm_config_loader.mdx b/api_docs/kbn_apm_config_loader.mdx index c4f8b6213ed6d0..41246db0a67567 100644 --- a/api_docs/kbn_apm_config_loader.mdx +++ b/api_docs/kbn_apm_config_loader.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-config-loader title: "@kbn/apm-config-loader" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-config-loader plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-config-loader'] --- import kbnApmConfigLoaderObj from './kbn_apm_config_loader.devdocs.json'; diff --git a/api_docs/kbn_apm_synthtrace.mdx b/api_docs/kbn_apm_synthtrace.mdx index a61909d3c54814..82c57310848d5d 100644 --- a/api_docs/kbn_apm_synthtrace.mdx +++ b/api_docs/kbn_apm_synthtrace.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-synthtrace title: "@kbn/apm-synthtrace" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-synthtrace plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-synthtrace'] --- import kbnApmSynthtraceObj from './kbn_apm_synthtrace.devdocs.json'; diff --git a/api_docs/kbn_apm_utils.mdx b/api_docs/kbn_apm_utils.mdx index c51c92f4e555b3..3b8859bf24577a 100644 --- a/api_docs/kbn_apm_utils.mdx +++ b/api_docs/kbn_apm_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-utils title: "@kbn/apm-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-utils plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-utils'] --- import kbnApmUtilsObj from './kbn_apm_utils.devdocs.json'; diff --git a/api_docs/kbn_axe_config.mdx b/api_docs/kbn_axe_config.mdx index 257134279eba5e..a84beaaf76f9c7 100644 --- a/api_docs/kbn_axe_config.mdx +++ b/api_docs/kbn_axe_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-axe-config title: "@kbn/axe-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/axe-config plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/axe-config'] --- import kbnAxeConfigObj from './kbn_axe_config.devdocs.json'; diff --git a/api_docs/kbn_chart_icons.mdx b/api_docs/kbn_chart_icons.mdx index 3145ac4c1a5ac2..f81ea7eb893f4c 100644 --- a/api_docs/kbn_chart_icons.mdx +++ b/api_docs/kbn_chart_icons.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-chart-icons title: "@kbn/chart-icons" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/chart-icons plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/chart-icons'] --- import kbnChartIconsObj from './kbn_chart_icons.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_core.mdx b/api_docs/kbn_ci_stats_core.mdx index 2ffa59cb7e82be..f136b1b4b9722e 100644 --- a/api_docs/kbn_ci_stats_core.mdx +++ b/api_docs/kbn_ci_stats_core.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-core title: "@kbn/ci-stats-core" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-core plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-core'] --- import kbnCiStatsCoreObj from './kbn_ci_stats_core.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_performance_metrics.mdx b/api_docs/kbn_ci_stats_performance_metrics.mdx index 2686b6b92199b7..4fac55f5f28f2f 100644 --- a/api_docs/kbn_ci_stats_performance_metrics.mdx +++ b/api_docs/kbn_ci_stats_performance_metrics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-performance-metrics title: "@kbn/ci-stats-performance-metrics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-performance-metrics plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-performance-metrics'] --- import kbnCiStatsPerformanceMetricsObj from './kbn_ci_stats_performance_metrics.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_reporter.mdx b/api_docs/kbn_ci_stats_reporter.mdx index 9f99819517f579..9a986e49442eb8 100644 --- a/api_docs/kbn_ci_stats_reporter.mdx +++ b/api_docs/kbn_ci_stats_reporter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-reporter title: "@kbn/ci-stats-reporter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-reporter plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-reporter'] --- import kbnCiStatsReporterObj from './kbn_ci_stats_reporter.devdocs.json'; diff --git a/api_docs/kbn_cli_dev_mode.mdx b/api_docs/kbn_cli_dev_mode.mdx index 296dc4ec77bac8..ad805a672ec6af 100644 --- a/api_docs/kbn_cli_dev_mode.mdx +++ b/api_docs/kbn_cli_dev_mode.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cli-dev-mode title: "@kbn/cli-dev-mode" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cli-dev-mode plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cli-dev-mode'] --- import kbnCliDevModeObj from './kbn_cli_dev_mode.devdocs.json'; diff --git a/api_docs/kbn_coloring.mdx b/api_docs/kbn_coloring.mdx index 94885afcb91623..d48d41a5c86497 100644 --- a/api_docs/kbn_coloring.mdx +++ b/api_docs/kbn_coloring.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-coloring title: "@kbn/coloring" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/coloring plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/coloring'] --- import kbnColoringObj from './kbn_coloring.devdocs.json'; diff --git a/api_docs/kbn_config.mdx b/api_docs/kbn_config.mdx index e5bf6e1dbfb83a..1e6fbb0c526198 100644 --- a/api_docs/kbn_config.mdx +++ b/api_docs/kbn_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config title: "@kbn/config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config'] --- import kbnConfigObj from './kbn_config.devdocs.json'; diff --git a/api_docs/kbn_config_mocks.mdx b/api_docs/kbn_config_mocks.mdx index 710c8557fec4ee..4ed5acbd873d26 100644 --- a/api_docs/kbn_config_mocks.mdx +++ b/api_docs/kbn_config_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config-mocks title: "@kbn/config-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-mocks'] --- import kbnConfigMocksObj from './kbn_config_mocks.devdocs.json'; diff --git a/api_docs/kbn_config_schema.mdx b/api_docs/kbn_config_schema.mdx index 59050347d3e1d6..1a85935c87425d 100644 --- a/api_docs/kbn_config_schema.mdx +++ b/api_docs/kbn_config_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config-schema title: "@kbn/config-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config-schema plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-schema'] --- import kbnConfigSchemaObj from './kbn_config_schema.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser.mdx b/api_docs/kbn_core_analytics_browser.mdx index 4de5f236edc48c..ac39a7961593a8 100644 --- a/api_docs/kbn_core_analytics_browser.mdx +++ b/api_docs/kbn_core_analytics_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser title: "@kbn/core-analytics-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser'] --- import kbnCoreAnalyticsBrowserObj from './kbn_core_analytics_browser.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser_internal.mdx b/api_docs/kbn_core_analytics_browser_internal.mdx index 17666254be1d69..fc5cd3bfb84380 100644 --- a/api_docs/kbn_core_analytics_browser_internal.mdx +++ b/api_docs/kbn_core_analytics_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser-internal title: "@kbn/core-analytics-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser-internal plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser-internal'] --- import kbnCoreAnalyticsBrowserInternalObj from './kbn_core_analytics_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser_mocks.mdx b/api_docs/kbn_core_analytics_browser_mocks.mdx index d1ab2d84b53c31..4c9c75e8523909 100644 --- a/api_docs/kbn_core_analytics_browser_mocks.mdx +++ b/api_docs/kbn_core_analytics_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser-mocks title: "@kbn/core-analytics-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser-mocks'] --- import kbnCoreAnalyticsBrowserMocksObj from './kbn_core_analytics_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server.mdx b/api_docs/kbn_core_analytics_server.mdx index 90bc6b5afe237a..92c14242978161 100644 --- a/api_docs/kbn_core_analytics_server.mdx +++ b/api_docs/kbn_core_analytics_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server title: "@kbn/core-analytics-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server'] --- import kbnCoreAnalyticsServerObj from './kbn_core_analytics_server.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server_internal.mdx b/api_docs/kbn_core_analytics_server_internal.mdx index 9d850e4df759d3..da3c85dc76a4e6 100644 --- a/api_docs/kbn_core_analytics_server_internal.mdx +++ b/api_docs/kbn_core_analytics_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server-internal title: "@kbn/core-analytics-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server-internal plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server-internal'] --- import kbnCoreAnalyticsServerInternalObj from './kbn_core_analytics_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server_mocks.mdx b/api_docs/kbn_core_analytics_server_mocks.mdx index c5d70f92b87507..e291353f701f69 100644 --- a/api_docs/kbn_core_analytics_server_mocks.mdx +++ b/api_docs/kbn_core_analytics_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server-mocks title: "@kbn/core-analytics-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server-mocks'] --- import kbnCoreAnalyticsServerMocksObj from './kbn_core_analytics_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser.mdx b/api_docs/kbn_core_application_browser.mdx index 6cc7d0b4866dbd..e1d48305d2290f 100644 --- a/api_docs/kbn_core_application_browser.mdx +++ b/api_docs/kbn_core_application_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser title: "@kbn/core-application-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser'] --- import kbnCoreApplicationBrowserObj from './kbn_core_application_browser.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser_internal.mdx b/api_docs/kbn_core_application_browser_internal.mdx index 79e8c34727b5dc..1b208d9a634874 100644 --- a/api_docs/kbn_core_application_browser_internal.mdx +++ b/api_docs/kbn_core_application_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser-internal title: "@kbn/core-application-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser-internal plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser-internal'] --- import kbnCoreApplicationBrowserInternalObj from './kbn_core_application_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser_mocks.mdx b/api_docs/kbn_core_application_browser_mocks.mdx index 44d5b180671ba4..3ad4f503057fac 100644 --- a/api_docs/kbn_core_application_browser_mocks.mdx +++ b/api_docs/kbn_core_application_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser-mocks title: "@kbn/core-application-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser-mocks'] --- import kbnCoreApplicationBrowserMocksObj from './kbn_core_application_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_application_common.mdx b/api_docs/kbn_core_application_common.mdx index 5a94eee634d9a8..4779f2f4f68b53 100644 --- a/api_docs/kbn_core_application_common.mdx +++ b/api_docs/kbn_core_application_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-common title: "@kbn/core-application-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-common plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-common'] --- import kbnCoreApplicationCommonObj from './kbn_core_application_common.devdocs.json'; diff --git a/api_docs/kbn_core_base_browser_mocks.mdx b/api_docs/kbn_core_base_browser_mocks.mdx index 915ba4547bc97d..701892c07d6fb6 100644 --- a/api_docs/kbn_core_base_browser_mocks.mdx +++ b/api_docs/kbn_core_base_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-browser-mocks title: "@kbn/core-base-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-browser-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-browser-mocks'] --- import kbnCoreBaseBrowserMocksObj from './kbn_core_base_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_base_common.mdx b/api_docs/kbn_core_base_common.mdx index 2531446c382d69..6f65974f3df957 100644 --- a/api_docs/kbn_core_base_common.mdx +++ b/api_docs/kbn_core_base_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-common title: "@kbn/core-base-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-common plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-common'] --- import kbnCoreBaseCommonObj from './kbn_core_base_common.devdocs.json'; diff --git a/api_docs/kbn_core_base_server_internal.mdx b/api_docs/kbn_core_base_server_internal.mdx index 327ea656abef08..3ac31dbf66d235 100644 --- a/api_docs/kbn_core_base_server_internal.mdx +++ b/api_docs/kbn_core_base_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-server-internal title: "@kbn/core-base-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-server-internal plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-server-internal'] --- import kbnCoreBaseServerInternalObj from './kbn_core_base_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_base_server_mocks.mdx b/api_docs/kbn_core_base_server_mocks.mdx index 141177c4ca7d8c..5d9da0822c070a 100644 --- a/api_docs/kbn_core_base_server_mocks.mdx +++ b/api_docs/kbn_core_base_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-server-mocks title: "@kbn/core-base-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-server-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-server-mocks'] --- import kbnCoreBaseServerMocksObj from './kbn_core_base_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_browser_mocks.mdx b/api_docs/kbn_core_capabilities_browser_mocks.mdx index 9a72ce6e4bb898..0fb84b17ee969d 100644 --- a/api_docs/kbn_core_capabilities_browser_mocks.mdx +++ b/api_docs/kbn_core_capabilities_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-browser-mocks title: "@kbn/core-capabilities-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-browser-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-browser-mocks'] --- import kbnCoreCapabilitiesBrowserMocksObj from './kbn_core_capabilities_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_common.mdx b/api_docs/kbn_core_capabilities_common.mdx index cb1ecb2091a92a..24dc0372c51ec7 100644 --- a/api_docs/kbn_core_capabilities_common.mdx +++ b/api_docs/kbn_core_capabilities_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-common title: "@kbn/core-capabilities-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-common plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-common'] --- import kbnCoreCapabilitiesCommonObj from './kbn_core_capabilities_common.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_server.mdx b/api_docs/kbn_core_capabilities_server.mdx index 91e709440cd60c..a52d64e5e6e200 100644 --- a/api_docs/kbn_core_capabilities_server.mdx +++ b/api_docs/kbn_core_capabilities_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-server title: "@kbn/core-capabilities-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-server plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-server'] --- import kbnCoreCapabilitiesServerObj from './kbn_core_capabilities_server.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_server_mocks.mdx b/api_docs/kbn_core_capabilities_server_mocks.mdx index 1ece686b0cdae1..5e2bfe3318f47c 100644 --- a/api_docs/kbn_core_capabilities_server_mocks.mdx +++ b/api_docs/kbn_core_capabilities_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-server-mocks title: "@kbn/core-capabilities-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-server-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-server-mocks'] --- import kbnCoreCapabilitiesServerMocksObj from './kbn_core_capabilities_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_chrome_browser.mdx b/api_docs/kbn_core_chrome_browser.mdx index b7d9a4fcabb3cf..8e3c4efe990f0d 100644 --- a/api_docs/kbn_core_chrome_browser.mdx +++ b/api_docs/kbn_core_chrome_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-chrome-browser title: "@kbn/core-chrome-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-chrome-browser plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-chrome-browser'] --- import kbnCoreChromeBrowserObj from './kbn_core_chrome_browser.devdocs.json'; diff --git a/api_docs/kbn_core_chrome_browser_mocks.mdx b/api_docs/kbn_core_chrome_browser_mocks.mdx index b13ad6b1d385c3..ecc9bc1bad7b3b 100644 --- a/api_docs/kbn_core_chrome_browser_mocks.mdx +++ b/api_docs/kbn_core_chrome_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-chrome-browser-mocks title: "@kbn/core-chrome-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-chrome-browser-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-chrome-browser-mocks'] --- import kbnCoreChromeBrowserMocksObj from './kbn_core_chrome_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_config_server_internal.mdx b/api_docs/kbn_core_config_server_internal.mdx index 828ecc68dc87d2..fa73a6310dd904 100644 --- a/api_docs/kbn_core_config_server_internal.mdx +++ b/api_docs/kbn_core_config_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-config-server-internal title: "@kbn/core-config-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-config-server-internal plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-config-server-internal'] --- import kbnCoreConfigServerInternalObj from './kbn_core_config_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser.mdx b/api_docs/kbn_core_deprecations_browser.mdx index 8d21dcce86b576..e9d543f5eab88e 100644 --- a/api_docs/kbn_core_deprecations_browser.mdx +++ b/api_docs/kbn_core_deprecations_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser title: "@kbn/core-deprecations-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser'] --- import kbnCoreDeprecationsBrowserObj from './kbn_core_deprecations_browser.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser_internal.mdx b/api_docs/kbn_core_deprecations_browser_internal.mdx index 9dc3dc1beaa13f..5e380c589df455 100644 --- a/api_docs/kbn_core_deprecations_browser_internal.mdx +++ b/api_docs/kbn_core_deprecations_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser-internal title: "@kbn/core-deprecations-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser-internal plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser-internal'] --- import kbnCoreDeprecationsBrowserInternalObj from './kbn_core_deprecations_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser_mocks.mdx b/api_docs/kbn_core_deprecations_browser_mocks.mdx index 4fd817133f4a41..86d55e1e9c44d1 100644 --- a/api_docs/kbn_core_deprecations_browser_mocks.mdx +++ b/api_docs/kbn_core_deprecations_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser-mocks title: "@kbn/core-deprecations-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser-mocks'] --- import kbnCoreDeprecationsBrowserMocksObj from './kbn_core_deprecations_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_common.mdx b/api_docs/kbn_core_deprecations_common.mdx index 764220009c8c77..6dd116c3c46f26 100644 --- a/api_docs/kbn_core_deprecations_common.mdx +++ b/api_docs/kbn_core_deprecations_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-common title: "@kbn/core-deprecations-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-common plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-common'] --- import kbnCoreDeprecationsCommonObj from './kbn_core_deprecations_common.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server.mdx b/api_docs/kbn_core_deprecations_server.mdx index 5280bca1562423..96418b9c64b682 100644 --- a/api_docs/kbn_core_deprecations_server.mdx +++ b/api_docs/kbn_core_deprecations_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server title: "@kbn/core-deprecations-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server'] --- import kbnCoreDeprecationsServerObj from './kbn_core_deprecations_server.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server_internal.mdx b/api_docs/kbn_core_deprecations_server_internal.mdx index 4f1b395e88650a..b557d4e5c473ab 100644 --- a/api_docs/kbn_core_deprecations_server_internal.mdx +++ b/api_docs/kbn_core_deprecations_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server-internal title: "@kbn/core-deprecations-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server-internal plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server-internal'] --- import kbnCoreDeprecationsServerInternalObj from './kbn_core_deprecations_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server_mocks.mdx b/api_docs/kbn_core_deprecations_server_mocks.mdx index f18fe6d87767e2..0cacd094cfbb99 100644 --- a/api_docs/kbn_core_deprecations_server_mocks.mdx +++ b/api_docs/kbn_core_deprecations_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server-mocks title: "@kbn/core-deprecations-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server-mocks'] --- import kbnCoreDeprecationsServerMocksObj from './kbn_core_deprecations_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_browser.mdx b/api_docs/kbn_core_doc_links_browser.mdx index 0ef4b6124c5a7a..2c72b3d00c5990 100644 --- a/api_docs/kbn_core_doc_links_browser.mdx +++ b/api_docs/kbn_core_doc_links_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-browser title: "@kbn/core-doc-links-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-browser plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-browser'] --- import kbnCoreDocLinksBrowserObj from './kbn_core_doc_links_browser.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_browser_mocks.mdx b/api_docs/kbn_core_doc_links_browser_mocks.mdx index 9a1b47c956f7b6..1582e2b3c6a478 100644 --- a/api_docs/kbn_core_doc_links_browser_mocks.mdx +++ b/api_docs/kbn_core_doc_links_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-browser-mocks title: "@kbn/core-doc-links-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-browser-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-browser-mocks'] --- import kbnCoreDocLinksBrowserMocksObj from './kbn_core_doc_links_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_server.mdx b/api_docs/kbn_core_doc_links_server.mdx index 775dfd58560ec8..7cad22cf1928bb 100644 --- a/api_docs/kbn_core_doc_links_server.mdx +++ b/api_docs/kbn_core_doc_links_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-server title: "@kbn/core-doc-links-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-server plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-server'] --- import kbnCoreDocLinksServerObj from './kbn_core_doc_links_server.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_server_mocks.mdx b/api_docs/kbn_core_doc_links_server_mocks.mdx index 5ec3e9e1678905..ac6c785eb5bbc8 100644 --- a/api_docs/kbn_core_doc_links_server_mocks.mdx +++ b/api_docs/kbn_core_doc_links_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-server-mocks title: "@kbn/core-doc-links-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-server-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-server-mocks'] --- import kbnCoreDocLinksServerMocksObj from './kbn_core_doc_links_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_client_server_internal.mdx b/api_docs/kbn_core_elasticsearch_client_server_internal.mdx index 4d0b32a2df8701..65546108902bde 100644 --- a/api_docs/kbn_core_elasticsearch_client_server_internal.mdx +++ b/api_docs/kbn_core_elasticsearch_client_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-client-server-internal title: "@kbn/core-elasticsearch-client-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-client-server-internal plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-client-server-internal'] --- import kbnCoreElasticsearchClientServerInternalObj from './kbn_core_elasticsearch_client_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx b/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx index a7c596885d1347..b119bfb2ad808a 100644 --- a/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx +++ b/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-client-server-mocks title: "@kbn/core-elasticsearch-client-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-client-server-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-client-server-mocks'] --- import kbnCoreElasticsearchClientServerMocksObj from './kbn_core_elasticsearch_client_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server.mdx b/api_docs/kbn_core_elasticsearch_server.mdx index e09bb332ab2e50..d8d8afa63313df 100644 --- a/api_docs/kbn_core_elasticsearch_server.mdx +++ b/api_docs/kbn_core_elasticsearch_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server title: "@kbn/core-elasticsearch-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server'] --- import kbnCoreElasticsearchServerObj from './kbn_core_elasticsearch_server.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server_internal.mdx b/api_docs/kbn_core_elasticsearch_server_internal.mdx index 13e1bfaed65347..7bb38a3c5f0bf3 100644 --- a/api_docs/kbn_core_elasticsearch_server_internal.mdx +++ b/api_docs/kbn_core_elasticsearch_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server-internal title: "@kbn/core-elasticsearch-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server-internal plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server-internal'] --- import kbnCoreElasticsearchServerInternalObj from './kbn_core_elasticsearch_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server_mocks.mdx b/api_docs/kbn_core_elasticsearch_server_mocks.mdx index d16344d577654d..da30359337d2fc 100644 --- a/api_docs/kbn_core_elasticsearch_server_mocks.mdx +++ b/api_docs/kbn_core_elasticsearch_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server-mocks title: "@kbn/core-elasticsearch-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server-mocks'] --- import kbnCoreElasticsearchServerMocksObj from './kbn_core_elasticsearch_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_environment_server_internal.mdx b/api_docs/kbn_core_environment_server_internal.mdx index b09975fb0b72e8..115eabde42da7c 100644 --- a/api_docs/kbn_core_environment_server_internal.mdx +++ b/api_docs/kbn_core_environment_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-environment-server-internal title: "@kbn/core-environment-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-environment-server-internal plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-environment-server-internal'] --- import kbnCoreEnvironmentServerInternalObj from './kbn_core_environment_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_environment_server_mocks.mdx b/api_docs/kbn_core_environment_server_mocks.mdx index ee59dc70817d6f..edfcddc56edc18 100644 --- a/api_docs/kbn_core_environment_server_mocks.mdx +++ b/api_docs/kbn_core_environment_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-environment-server-mocks title: "@kbn/core-environment-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-environment-server-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-environment-server-mocks'] --- import kbnCoreEnvironmentServerMocksObj from './kbn_core_environment_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser.mdx b/api_docs/kbn_core_execution_context_browser.mdx index f6dea3c2cc1dea..6d3b3e2cf0095e 100644 --- a/api_docs/kbn_core_execution_context_browser.mdx +++ b/api_docs/kbn_core_execution_context_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser title: "@kbn/core-execution-context-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser'] --- import kbnCoreExecutionContextBrowserObj from './kbn_core_execution_context_browser.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser_internal.mdx b/api_docs/kbn_core_execution_context_browser_internal.mdx index a26edda217b05c..fcc2284968ba8b 100644 --- a/api_docs/kbn_core_execution_context_browser_internal.mdx +++ b/api_docs/kbn_core_execution_context_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser-internal title: "@kbn/core-execution-context-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser-internal plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser-internal'] --- import kbnCoreExecutionContextBrowserInternalObj from './kbn_core_execution_context_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser_mocks.mdx b/api_docs/kbn_core_execution_context_browser_mocks.mdx index 9fd9f56b7aab3e..48919a14adc5da 100644 --- a/api_docs/kbn_core_execution_context_browser_mocks.mdx +++ b/api_docs/kbn_core_execution_context_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser-mocks title: "@kbn/core-execution-context-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser-mocks'] --- import kbnCoreExecutionContextBrowserMocksObj from './kbn_core_execution_context_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_common.mdx b/api_docs/kbn_core_execution_context_common.mdx index 8e8d4a6de07ba9..0a87811f9fa6d1 100644 --- a/api_docs/kbn_core_execution_context_common.mdx +++ b/api_docs/kbn_core_execution_context_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-common title: "@kbn/core-execution-context-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-common plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-common'] --- import kbnCoreExecutionContextCommonObj from './kbn_core_execution_context_common.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server.mdx b/api_docs/kbn_core_execution_context_server.mdx index ecc1b11cd5720b..be640b0bd6c12f 100644 --- a/api_docs/kbn_core_execution_context_server.mdx +++ b/api_docs/kbn_core_execution_context_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server title: "@kbn/core-execution-context-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server'] --- import kbnCoreExecutionContextServerObj from './kbn_core_execution_context_server.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server_internal.mdx b/api_docs/kbn_core_execution_context_server_internal.mdx index 4d2cdfc603e74b..4d9363ee6d0670 100644 --- a/api_docs/kbn_core_execution_context_server_internal.mdx +++ b/api_docs/kbn_core_execution_context_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server-internal title: "@kbn/core-execution-context-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server-internal plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server-internal'] --- import kbnCoreExecutionContextServerInternalObj from './kbn_core_execution_context_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server_mocks.mdx b/api_docs/kbn_core_execution_context_server_mocks.mdx index 1c512cf314176f..8e1632be18c1bc 100644 --- a/api_docs/kbn_core_execution_context_server_mocks.mdx +++ b/api_docs/kbn_core_execution_context_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server-mocks title: "@kbn/core-execution-context-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server-mocks'] --- import kbnCoreExecutionContextServerMocksObj from './kbn_core_execution_context_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_fatal_errors_browser.mdx b/api_docs/kbn_core_fatal_errors_browser.mdx index cb87d0d5251cb2..7fee5984f817aa 100644 --- a/api_docs/kbn_core_fatal_errors_browser.mdx +++ b/api_docs/kbn_core_fatal_errors_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-fatal-errors-browser title: "@kbn/core-fatal-errors-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-fatal-errors-browser plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-fatal-errors-browser'] --- import kbnCoreFatalErrorsBrowserObj from './kbn_core_fatal_errors_browser.devdocs.json'; diff --git a/api_docs/kbn_core_fatal_errors_browser_mocks.mdx b/api_docs/kbn_core_fatal_errors_browser_mocks.mdx index 6193837154b113..c989c3c38eff42 100644 --- a/api_docs/kbn_core_fatal_errors_browser_mocks.mdx +++ b/api_docs/kbn_core_fatal_errors_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-fatal-errors-browser-mocks title: "@kbn/core-fatal-errors-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-fatal-errors-browser-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-fatal-errors-browser-mocks'] --- import kbnCoreFatalErrorsBrowserMocksObj from './kbn_core_fatal_errors_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser.mdx b/api_docs/kbn_core_http_browser.mdx index 90a5aabdce8e64..ab44b913d6d22f 100644 --- a/api_docs/kbn_core_http_browser.mdx +++ b/api_docs/kbn_core_http_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser title: "@kbn/core-http-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser'] --- import kbnCoreHttpBrowserObj from './kbn_core_http_browser.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser_internal.mdx b/api_docs/kbn_core_http_browser_internal.mdx index 9d4d347bf3d572..a23bfab2355724 100644 --- a/api_docs/kbn_core_http_browser_internal.mdx +++ b/api_docs/kbn_core_http_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser-internal title: "@kbn/core-http-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser-internal plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser-internal'] --- import kbnCoreHttpBrowserInternalObj from './kbn_core_http_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser_mocks.mdx b/api_docs/kbn_core_http_browser_mocks.mdx index 4a14e036c3bfdc..cc4ba299fcd2f8 100644 --- a/api_docs/kbn_core_http_browser_mocks.mdx +++ b/api_docs/kbn_core_http_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser-mocks title: "@kbn/core-http-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser-mocks'] --- import kbnCoreHttpBrowserMocksObj from './kbn_core_http_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_common.mdx b/api_docs/kbn_core_http_common.mdx index 1b84ca589506b4..f3ad4235ca0bdd 100644 --- a/api_docs/kbn_core_http_common.mdx +++ b/api_docs/kbn_core_http_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-common title: "@kbn/core-http-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-common plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-common'] --- import kbnCoreHttpCommonObj from './kbn_core_http_common.devdocs.json'; diff --git a/api_docs/kbn_core_http_context_server_mocks.mdx b/api_docs/kbn_core_http_context_server_mocks.mdx index 35a8438855f439..8e036459534723 100644 --- a/api_docs/kbn_core_http_context_server_mocks.mdx +++ b/api_docs/kbn_core_http_context_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-context-server-mocks title: "@kbn/core-http-context-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-context-server-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-context-server-mocks'] --- import kbnCoreHttpContextServerMocksObj from './kbn_core_http_context_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_router_server_internal.mdx b/api_docs/kbn_core_http_router_server_internal.mdx index 5e0c00cb2c821d..cd7e2beebf898a 100644 --- a/api_docs/kbn_core_http_router_server_internal.mdx +++ b/api_docs/kbn_core_http_router_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-router-server-internal title: "@kbn/core-http-router-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-router-server-internal plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-router-server-internal'] --- import kbnCoreHttpRouterServerInternalObj from './kbn_core_http_router_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_router_server_mocks.mdx b/api_docs/kbn_core_http_router_server_mocks.mdx index 10a9676bf1c528..355ed41119b58b 100644 --- a/api_docs/kbn_core_http_router_server_mocks.mdx +++ b/api_docs/kbn_core_http_router_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-router-server-mocks title: "@kbn/core-http-router-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-router-server-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-router-server-mocks'] --- import kbnCoreHttpRouterServerMocksObj from './kbn_core_http_router_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_server.mdx b/api_docs/kbn_core_http_server.mdx index cc27eb8d1928f6..bca3d59fc66ba0 100644 --- a/api_docs/kbn_core_http_server.mdx +++ b/api_docs/kbn_core_http_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server title: "@kbn/core-http-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server'] --- import kbnCoreHttpServerObj from './kbn_core_http_server.devdocs.json'; diff --git a/api_docs/kbn_core_http_server_internal.mdx b/api_docs/kbn_core_http_server_internal.mdx index a6a4ea0f0dabb2..8c1ce95e5da381 100644 --- a/api_docs/kbn_core_http_server_internal.mdx +++ b/api_docs/kbn_core_http_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server-internal title: "@kbn/core-http-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server-internal plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server-internal'] --- import kbnCoreHttpServerInternalObj from './kbn_core_http_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_server_mocks.mdx b/api_docs/kbn_core_http_server_mocks.mdx index 4bc5202d1ecbbc..9855a467f8ff3a 100644 --- a/api_docs/kbn_core_http_server_mocks.mdx +++ b/api_docs/kbn_core_http_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server-mocks title: "@kbn/core-http-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server-mocks'] --- import kbnCoreHttpServerMocksObj from './kbn_core_http_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_browser.mdx b/api_docs/kbn_core_i18n_browser.mdx index dc6fe251ed8c84..e10bab2bb0ef1d 100644 --- a/api_docs/kbn_core_i18n_browser.mdx +++ b/api_docs/kbn_core_i18n_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-browser title: "@kbn/core-i18n-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-browser plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-browser'] --- import kbnCoreI18nBrowserObj from './kbn_core_i18n_browser.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_browser_mocks.mdx b/api_docs/kbn_core_i18n_browser_mocks.mdx index 96a1d3df89f074..6bbcf9a1ed58f1 100644 --- a/api_docs/kbn_core_i18n_browser_mocks.mdx +++ b/api_docs/kbn_core_i18n_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-browser-mocks title: "@kbn/core-i18n-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-browser-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-browser-mocks'] --- import kbnCoreI18nBrowserMocksObj from './kbn_core_i18n_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server.mdx b/api_docs/kbn_core_i18n_server.mdx index 50e3d68961707b..ca0b28fad3b83b 100644 --- a/api_docs/kbn_core_i18n_server.mdx +++ b/api_docs/kbn_core_i18n_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server title: "@kbn/core-i18n-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server'] --- import kbnCoreI18nServerObj from './kbn_core_i18n_server.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server_internal.mdx b/api_docs/kbn_core_i18n_server_internal.mdx index 5f59dd23c1b7e1..d0b3e5f8750ae1 100644 --- a/api_docs/kbn_core_i18n_server_internal.mdx +++ b/api_docs/kbn_core_i18n_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server-internal title: "@kbn/core-i18n-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server-internal plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server-internal'] --- import kbnCoreI18nServerInternalObj from './kbn_core_i18n_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server_mocks.mdx b/api_docs/kbn_core_i18n_server_mocks.mdx index d357516e5ab342..09595678ffd95d 100644 --- a/api_docs/kbn_core_i18n_server_mocks.mdx +++ b/api_docs/kbn_core_i18n_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server-mocks title: "@kbn/core-i18n-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server-mocks'] --- import kbnCoreI18nServerMocksObj from './kbn_core_i18n_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_injected_metadata_browser.mdx b/api_docs/kbn_core_injected_metadata_browser.mdx index 2749fcaffc1ea5..f98bc4b4caa51a 100644 --- a/api_docs/kbn_core_injected_metadata_browser.mdx +++ b/api_docs/kbn_core_injected_metadata_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-injected-metadata-browser title: "@kbn/core-injected-metadata-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-injected-metadata-browser plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-injected-metadata-browser'] --- import kbnCoreInjectedMetadataBrowserObj from './kbn_core_injected_metadata_browser.devdocs.json'; diff --git a/api_docs/kbn_core_injected_metadata_browser_mocks.mdx b/api_docs/kbn_core_injected_metadata_browser_mocks.mdx index adec64f1dfcbc0..2d6f60b30b0f4b 100644 --- a/api_docs/kbn_core_injected_metadata_browser_mocks.mdx +++ b/api_docs/kbn_core_injected_metadata_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-injected-metadata-browser-mocks title: "@kbn/core-injected-metadata-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-injected-metadata-browser-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-injected-metadata-browser-mocks'] --- import kbnCoreInjectedMetadataBrowserMocksObj from './kbn_core_injected_metadata_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_integrations_browser_internal.mdx b/api_docs/kbn_core_integrations_browser_internal.mdx index db081dbbe83b80..7d6d538a4a3453 100644 --- a/api_docs/kbn_core_integrations_browser_internal.mdx +++ b/api_docs/kbn_core_integrations_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-integrations-browser-internal title: "@kbn/core-integrations-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-integrations-browser-internal plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-integrations-browser-internal'] --- import kbnCoreIntegrationsBrowserInternalObj from './kbn_core_integrations_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_integrations_browser_mocks.mdx b/api_docs/kbn_core_integrations_browser_mocks.mdx index 37bd05952de416..965b44c3d7f494 100644 --- a/api_docs/kbn_core_integrations_browser_mocks.mdx +++ b/api_docs/kbn_core_integrations_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-integrations-browser-mocks title: "@kbn/core-integrations-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-integrations-browser-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-integrations-browser-mocks'] --- import kbnCoreIntegrationsBrowserMocksObj from './kbn_core_integrations_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server.mdx b/api_docs/kbn_core_logging_server.mdx index da345f5bb47c4f..baf526633cb7fa 100644 --- a/api_docs/kbn_core_logging_server.mdx +++ b/api_docs/kbn_core_logging_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server title: "@kbn/core-logging-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server'] --- import kbnCoreLoggingServerObj from './kbn_core_logging_server.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server_internal.mdx b/api_docs/kbn_core_logging_server_internal.mdx index 6cef90a03ccc29..c7e3e793271dc5 100644 --- a/api_docs/kbn_core_logging_server_internal.mdx +++ b/api_docs/kbn_core_logging_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server-internal title: "@kbn/core-logging-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server-internal plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server-internal'] --- import kbnCoreLoggingServerInternalObj from './kbn_core_logging_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server_mocks.mdx b/api_docs/kbn_core_logging_server_mocks.mdx index 82846fbbdc165d..ba256a3dc7685e 100644 --- a/api_docs/kbn_core_logging_server_mocks.mdx +++ b/api_docs/kbn_core_logging_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server-mocks title: "@kbn/core-logging-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server-mocks'] --- import kbnCoreLoggingServerMocksObj from './kbn_core_logging_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_collectors_server_internal.mdx b/api_docs/kbn_core_metrics_collectors_server_internal.mdx index 3eb7c726c850cd..20ddad2be7f374 100644 --- a/api_docs/kbn_core_metrics_collectors_server_internal.mdx +++ b/api_docs/kbn_core_metrics_collectors_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-collectors-server-internal title: "@kbn/core-metrics-collectors-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-collectors-server-internal plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-collectors-server-internal'] --- import kbnCoreMetricsCollectorsServerInternalObj from './kbn_core_metrics_collectors_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_collectors_server_mocks.mdx b/api_docs/kbn_core_metrics_collectors_server_mocks.mdx index bd93c7b2140cd1..6278558d4a15bd 100644 --- a/api_docs/kbn_core_metrics_collectors_server_mocks.mdx +++ b/api_docs/kbn_core_metrics_collectors_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-collectors-server-mocks title: "@kbn/core-metrics-collectors-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-collectors-server-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-collectors-server-mocks'] --- import kbnCoreMetricsCollectorsServerMocksObj from './kbn_core_metrics_collectors_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server.mdx b/api_docs/kbn_core_metrics_server.mdx index 670ecb0047f88a..774dbb4aa58f22 100644 --- a/api_docs/kbn_core_metrics_server.mdx +++ b/api_docs/kbn_core_metrics_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server title: "@kbn/core-metrics-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server'] --- import kbnCoreMetricsServerObj from './kbn_core_metrics_server.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server_internal.mdx b/api_docs/kbn_core_metrics_server_internal.mdx index 6599bf7ea1ddc6..b68f29089b3c5e 100644 --- a/api_docs/kbn_core_metrics_server_internal.mdx +++ b/api_docs/kbn_core_metrics_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server-internal title: "@kbn/core-metrics-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server-internal plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server-internal'] --- import kbnCoreMetricsServerInternalObj from './kbn_core_metrics_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server_mocks.mdx b/api_docs/kbn_core_metrics_server_mocks.mdx index 93282d37b74255..9da56c2b13d540 100644 --- a/api_docs/kbn_core_metrics_server_mocks.mdx +++ b/api_docs/kbn_core_metrics_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server-mocks title: "@kbn/core-metrics-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server-mocks'] --- import kbnCoreMetricsServerMocksObj from './kbn_core_metrics_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_mount_utils_browser.mdx b/api_docs/kbn_core_mount_utils_browser.mdx index d2c851b81781a5..fc5ad5407ea58e 100644 --- a/api_docs/kbn_core_mount_utils_browser.mdx +++ b/api_docs/kbn_core_mount_utils_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-mount-utils-browser title: "@kbn/core-mount-utils-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-mount-utils-browser plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-mount-utils-browser'] --- import kbnCoreMountUtilsBrowserObj from './kbn_core_mount_utils_browser.devdocs.json'; diff --git a/api_docs/kbn_core_node_server.mdx b/api_docs/kbn_core_node_server.mdx index 77d6ff98aa62d7..cbc248a380a6eb 100644 --- a/api_docs/kbn_core_node_server.mdx +++ b/api_docs/kbn_core_node_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server title: "@kbn/core-node-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server'] --- import kbnCoreNodeServerObj from './kbn_core_node_server.devdocs.json'; diff --git a/api_docs/kbn_core_node_server_internal.mdx b/api_docs/kbn_core_node_server_internal.mdx index 66355017e7862d..6c389f91fb1dee 100644 --- a/api_docs/kbn_core_node_server_internal.mdx +++ b/api_docs/kbn_core_node_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server-internal title: "@kbn/core-node-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server-internal plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server-internal'] --- import kbnCoreNodeServerInternalObj from './kbn_core_node_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_node_server_mocks.mdx b/api_docs/kbn_core_node_server_mocks.mdx index a9b52f33294ccb..e8223e2b459771 100644 --- a/api_docs/kbn_core_node_server_mocks.mdx +++ b/api_docs/kbn_core_node_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server-mocks title: "@kbn/core-node-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server-mocks'] --- import kbnCoreNodeServerMocksObj from './kbn_core_node_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser.mdx b/api_docs/kbn_core_notifications_browser.mdx index 19f30064d6411d..2c27b78aff6bb7 100644 --- a/api_docs/kbn_core_notifications_browser.mdx +++ b/api_docs/kbn_core_notifications_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser title: "@kbn/core-notifications-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser'] --- import kbnCoreNotificationsBrowserObj from './kbn_core_notifications_browser.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser_internal.mdx b/api_docs/kbn_core_notifications_browser_internal.mdx index 352ec11d502c96..197b80b4ba6304 100644 --- a/api_docs/kbn_core_notifications_browser_internal.mdx +++ b/api_docs/kbn_core_notifications_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser-internal title: "@kbn/core-notifications-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser-internal plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser-internal'] --- import kbnCoreNotificationsBrowserInternalObj from './kbn_core_notifications_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser_mocks.mdx b/api_docs/kbn_core_notifications_browser_mocks.mdx index 1c62b624f27e2e..bf9b1d6b28607d 100644 --- a/api_docs/kbn_core_notifications_browser_mocks.mdx +++ b/api_docs/kbn_core_notifications_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser-mocks title: "@kbn/core-notifications-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser-mocks'] --- import kbnCoreNotificationsBrowserMocksObj from './kbn_core_notifications_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser.mdx b/api_docs/kbn_core_overlays_browser.mdx index 9733b1627a6f7d..21561dfeb133d9 100644 --- a/api_docs/kbn_core_overlays_browser.mdx +++ b/api_docs/kbn_core_overlays_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser title: "@kbn/core-overlays-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser'] --- import kbnCoreOverlaysBrowserObj from './kbn_core_overlays_browser.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser_internal.mdx b/api_docs/kbn_core_overlays_browser_internal.mdx index 7119b50426bcf7..d4790272c355d5 100644 --- a/api_docs/kbn_core_overlays_browser_internal.mdx +++ b/api_docs/kbn_core_overlays_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser-internal title: "@kbn/core-overlays-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser-internal plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser-internal'] --- import kbnCoreOverlaysBrowserInternalObj from './kbn_core_overlays_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser_mocks.mdx b/api_docs/kbn_core_overlays_browser_mocks.mdx index 96f8c80736c1ea..1e44984b977aef 100644 --- a/api_docs/kbn_core_overlays_browser_mocks.mdx +++ b/api_docs/kbn_core_overlays_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser-mocks title: "@kbn/core-overlays-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser-mocks'] --- import kbnCoreOverlaysBrowserMocksObj from './kbn_core_overlays_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_preboot_server.mdx b/api_docs/kbn_core_preboot_server.mdx index c89e256f923c28..064c1a7409c91d 100644 --- a/api_docs/kbn_core_preboot_server.mdx +++ b/api_docs/kbn_core_preboot_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-preboot-server title: "@kbn/core-preboot-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-preboot-server plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-preboot-server'] --- import kbnCorePrebootServerObj from './kbn_core_preboot_server.devdocs.json'; diff --git a/api_docs/kbn_core_preboot_server_mocks.mdx b/api_docs/kbn_core_preboot_server_mocks.mdx index 0d82287ffaa818..68d8ba8c77e35a 100644 --- a/api_docs/kbn_core_preboot_server_mocks.mdx +++ b/api_docs/kbn_core_preboot_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-preboot-server-mocks title: "@kbn/core-preboot-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-preboot-server-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-preboot-server-mocks'] --- import kbnCorePrebootServerMocksObj from './kbn_core_preboot_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_rendering_browser_mocks.mdx b/api_docs/kbn_core_rendering_browser_mocks.mdx index 4905bd829e23ab..33c45bca370dbd 100644 --- a/api_docs/kbn_core_rendering_browser_mocks.mdx +++ b/api_docs/kbn_core_rendering_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-browser-mocks title: "@kbn/core-rendering-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-browser-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-rendering-browser-mocks'] --- import kbnCoreRenderingBrowserMocksObj from './kbn_core_rendering_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_browser.mdx b/api_docs/kbn_core_saved_objects_api_browser.mdx index 105532e5fb3b56..8fb776cf682400 100644 --- a/api_docs/kbn_core_saved_objects_api_browser.mdx +++ b/api_docs/kbn_core_saved_objects_api_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-browser title: "@kbn/core-saved-objects-api-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-browser plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-browser'] --- import kbnCoreSavedObjectsApiBrowserObj from './kbn_core_saved_objects_api_browser.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_server.mdx b/api_docs/kbn_core_saved_objects_api_server.mdx index 437f5d3e1d6e77..37b831645698d9 100644 --- a/api_docs/kbn_core_saved_objects_api_server.mdx +++ b/api_docs/kbn_core_saved_objects_api_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server title: "@kbn/core-saved-objects-api-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server'] --- import kbnCoreSavedObjectsApiServerObj from './kbn_core_saved_objects_api_server.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_server_internal.mdx b/api_docs/kbn_core_saved_objects_api_server_internal.mdx index 35f9be419d40c9..b1e0f26591dea8 100644 --- a/api_docs/kbn_core_saved_objects_api_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_api_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server-internal title: "@kbn/core-saved-objects-api-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server-internal plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server-internal'] --- import kbnCoreSavedObjectsApiServerInternalObj from './kbn_core_saved_objects_api_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_server_mocks.mdx b/api_docs/kbn_core_saved_objects_api_server_mocks.mdx index 5102602665f5bf..76e68572653434 100644 --- a/api_docs/kbn_core_saved_objects_api_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_api_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server-mocks title: "@kbn/core-saved-objects-api-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server-mocks'] --- import kbnCoreSavedObjectsApiServerMocksObj from './kbn_core_saved_objects_api_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_base_server_internal.mdx b/api_docs/kbn_core_saved_objects_base_server_internal.mdx index d78c3da1e3c01f..b0656d2d7698c9 100644 --- a/api_docs/kbn_core_saved_objects_base_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_base_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-base-server-internal title: "@kbn/core-saved-objects-base-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-base-server-internal plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-base-server-internal'] --- import kbnCoreSavedObjectsBaseServerInternalObj from './kbn_core_saved_objects_base_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_base_server_mocks.mdx b/api_docs/kbn_core_saved_objects_base_server_mocks.mdx index 0b40e8600a5b88..ecd8eb6b89e587 100644 --- a/api_docs/kbn_core_saved_objects_base_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_base_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-base-server-mocks title: "@kbn/core-saved-objects-base-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-base-server-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-base-server-mocks'] --- import kbnCoreSavedObjectsBaseServerMocksObj from './kbn_core_saved_objects_base_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser.mdx b/api_docs/kbn_core_saved_objects_browser.mdx index 586e42b8bf893d..3095a10b0e8a37 100644 --- a/api_docs/kbn_core_saved_objects_browser.mdx +++ b/api_docs/kbn_core_saved_objects_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser title: "@kbn/core-saved-objects-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser'] --- import kbnCoreSavedObjectsBrowserObj from './kbn_core_saved_objects_browser.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser_internal.mdx b/api_docs/kbn_core_saved_objects_browser_internal.mdx index 4f927190b7dd30..6e6235f54d936e 100644 --- a/api_docs/kbn_core_saved_objects_browser_internal.mdx +++ b/api_docs/kbn_core_saved_objects_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser-internal title: "@kbn/core-saved-objects-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser-internal plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser-internal'] --- import kbnCoreSavedObjectsBrowserInternalObj from './kbn_core_saved_objects_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser_mocks.mdx b/api_docs/kbn_core_saved_objects_browser_mocks.mdx index ab33dc4970f31e..9ba194c06f4bd5 100644 --- a/api_docs/kbn_core_saved_objects_browser_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser-mocks title: "@kbn/core-saved-objects-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser-mocks'] --- import kbnCoreSavedObjectsBrowserMocksObj from './kbn_core_saved_objects_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_common.mdx b/api_docs/kbn_core_saved_objects_common.mdx index 96477a0e7c797c..841d63be63be47 100644 --- a/api_docs/kbn_core_saved_objects_common.mdx +++ b/api_docs/kbn_core_saved_objects_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-common title: "@kbn/core-saved-objects-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-common plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-common'] --- import kbnCoreSavedObjectsCommonObj from './kbn_core_saved_objects_common.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx b/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx index 9e65224dc4a22d..62ca0892a8ef0f 100644 --- a/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-import-export-server-internal title: "@kbn/core-saved-objects-import-export-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-import-export-server-internal plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-import-export-server-internal'] --- import kbnCoreSavedObjectsImportExportServerInternalObj from './kbn_core_saved_objects_import_export_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx b/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx index 5169834e61594d..6db912ca3d51da 100644 --- a/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-import-export-server-mocks title: "@kbn/core-saved-objects-import-export-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-import-export-server-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-import-export-server-mocks'] --- import kbnCoreSavedObjectsImportExportServerMocksObj from './kbn_core_saved_objects_import_export_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_migration_server_internal.mdx b/api_docs/kbn_core_saved_objects_migration_server_internal.mdx index 0da4633a1f7d5a..124ba03f2d7cb0 100644 --- a/api_docs/kbn_core_saved_objects_migration_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_migration_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-migration-server-internal title: "@kbn/core-saved-objects-migration-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-migration-server-internal plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-migration-server-internal'] --- import kbnCoreSavedObjectsMigrationServerInternalObj from './kbn_core_saved_objects_migration_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx b/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx index 878e93723383bb..436795ec64440f 100644 --- a/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-migration-server-mocks title: "@kbn/core-saved-objects-migration-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-migration-server-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-migration-server-mocks'] --- import kbnCoreSavedObjectsMigrationServerMocksObj from './kbn_core_saved_objects_migration_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server.mdx b/api_docs/kbn_core_saved_objects_server.mdx index b50e4f961b89e2..d39b682d0e9227 100644 --- a/api_docs/kbn_core_saved_objects_server.mdx +++ b/api_docs/kbn_core_saved_objects_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server title: "@kbn/core-saved-objects-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server'] --- import kbnCoreSavedObjectsServerObj from './kbn_core_saved_objects_server.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server_internal.mdx b/api_docs/kbn_core_saved_objects_server_internal.mdx index f5b7858d33f53d..097b612967b60f 100644 --- a/api_docs/kbn_core_saved_objects_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server-internal title: "@kbn/core-saved-objects-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server-internal plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server-internal'] --- import kbnCoreSavedObjectsServerInternalObj from './kbn_core_saved_objects_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server_mocks.mdx b/api_docs/kbn_core_saved_objects_server_mocks.mdx index 9d97b89c2f36c3..5cfc809e628d45 100644 --- a/api_docs/kbn_core_saved_objects_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server-mocks title: "@kbn/core-saved-objects-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server-mocks'] --- import kbnCoreSavedObjectsServerMocksObj from './kbn_core_saved_objects_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_utils_server.mdx b/api_docs/kbn_core_saved_objects_utils_server.mdx index 415cc81dd6cdcc..0735565b60ba30 100644 --- a/api_docs/kbn_core_saved_objects_utils_server.mdx +++ b/api_docs/kbn_core_saved_objects_utils_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-utils-server title: "@kbn/core-saved-objects-utils-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-utils-server plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-utils-server'] --- import kbnCoreSavedObjectsUtilsServerObj from './kbn_core_saved_objects_utils_server.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_deprecations_getters.mdx b/api_docs/kbn_core_test_helpers_deprecations_getters.mdx index aaf942ddf2b324..bcc58ce97c1720 100644 --- a/api_docs/kbn_core_test_helpers_deprecations_getters.mdx +++ b/api_docs/kbn_core_test_helpers_deprecations_getters.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-deprecations-getters title: "@kbn/core-test-helpers-deprecations-getters" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-deprecations-getters plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-deprecations-getters'] --- import kbnCoreTestHelpersDeprecationsGettersObj from './kbn_core_test_helpers_deprecations_getters.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_http_setup_browser.mdx b/api_docs/kbn_core_test_helpers_http_setup_browser.mdx index 83e3c09e6f3222..fab15b3ed6f35a 100644 --- a/api_docs/kbn_core_test_helpers_http_setup_browser.mdx +++ b/api_docs/kbn_core_test_helpers_http_setup_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-http-setup-browser title: "@kbn/core-test-helpers-http-setup-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-http-setup-browser plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-http-setup-browser'] --- import kbnCoreTestHelpersHttpSetupBrowserObj from './kbn_core_test_helpers_http_setup_browser.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser.mdx b/api_docs/kbn_core_theme_browser.mdx index 62e874e46202f3..017403c279a718 100644 --- a/api_docs/kbn_core_theme_browser.mdx +++ b/api_docs/kbn_core_theme_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser title: "@kbn/core-theme-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser'] --- import kbnCoreThemeBrowserObj from './kbn_core_theme_browser.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser_internal.mdx b/api_docs/kbn_core_theme_browser_internal.mdx index 9537871eeff345..4b18d3cb540b5c 100644 --- a/api_docs/kbn_core_theme_browser_internal.mdx +++ b/api_docs/kbn_core_theme_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser-internal title: "@kbn/core-theme-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser-internal plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser-internal'] --- import kbnCoreThemeBrowserInternalObj from './kbn_core_theme_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser_mocks.mdx b/api_docs/kbn_core_theme_browser_mocks.mdx index beebf1fdcc401e..d68eda65b74784 100644 --- a/api_docs/kbn_core_theme_browser_mocks.mdx +++ b/api_docs/kbn_core_theme_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser-mocks title: "@kbn/core-theme-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser-mocks'] --- import kbnCoreThemeBrowserMocksObj from './kbn_core_theme_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser.mdx b/api_docs/kbn_core_ui_settings_browser.mdx index ef2df898310fa8..d43b64677389ad 100644 --- a/api_docs/kbn_core_ui_settings_browser.mdx +++ b/api_docs/kbn_core_ui_settings_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser title: "@kbn/core-ui-settings-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser'] --- import kbnCoreUiSettingsBrowserObj from './kbn_core_ui_settings_browser.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser_internal.mdx b/api_docs/kbn_core_ui_settings_browser_internal.mdx index 09ed2bcd433de1..a2b638ea5c8f3b 100644 --- a/api_docs/kbn_core_ui_settings_browser_internal.mdx +++ b/api_docs/kbn_core_ui_settings_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser-internal title: "@kbn/core-ui-settings-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser-internal plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser-internal'] --- import kbnCoreUiSettingsBrowserInternalObj from './kbn_core_ui_settings_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser_mocks.mdx b/api_docs/kbn_core_ui_settings_browser_mocks.mdx index 9a154dff10020e..6a7ad1ab8e14d6 100644 --- a/api_docs/kbn_core_ui_settings_browser_mocks.mdx +++ b/api_docs/kbn_core_ui_settings_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser-mocks title: "@kbn/core-ui-settings-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser-mocks'] --- import kbnCoreUiSettingsBrowserMocksObj from './kbn_core_ui_settings_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_common.mdx b/api_docs/kbn_core_ui_settings_common.mdx index b49506a87cfaa2..9b16f81a2be4a9 100644 --- a/api_docs/kbn_core_ui_settings_common.mdx +++ b/api_docs/kbn_core_ui_settings_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-common title: "@kbn/core-ui-settings-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-common plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-common'] --- import kbnCoreUiSettingsCommonObj from './kbn_core_ui_settings_common.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server.mdx b/api_docs/kbn_core_usage_data_server.mdx index d2da3e366390df..135387c16286c8 100644 --- a/api_docs/kbn_core_usage_data_server.mdx +++ b/api_docs/kbn_core_usage_data_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server title: "@kbn/core-usage-data-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server'] --- import kbnCoreUsageDataServerObj from './kbn_core_usage_data_server.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server_internal.mdx b/api_docs/kbn_core_usage_data_server_internal.mdx index 81d238bf3469ec..cb5b74bd34c0bd 100644 --- a/api_docs/kbn_core_usage_data_server_internal.mdx +++ b/api_docs/kbn_core_usage_data_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server-internal title: "@kbn/core-usage-data-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server-internal plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server-internal'] --- import kbnCoreUsageDataServerInternalObj from './kbn_core_usage_data_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server_mocks.mdx b/api_docs/kbn_core_usage_data_server_mocks.mdx index 0a453d4f366076..02f152900b4477 100644 --- a/api_docs/kbn_core_usage_data_server_mocks.mdx +++ b/api_docs/kbn_core_usage_data_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server-mocks title: "@kbn/core-usage-data-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server-mocks'] --- import kbnCoreUsageDataServerMocksObj from './kbn_core_usage_data_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_crypto.mdx b/api_docs/kbn_crypto.mdx index ceca8f916777de..70e8d69a6b17cb 100644 --- a/api_docs/kbn_crypto.mdx +++ b/api_docs/kbn_crypto.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-crypto title: "@kbn/crypto" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/crypto plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto'] --- import kbnCryptoObj from './kbn_crypto.devdocs.json'; diff --git a/api_docs/kbn_crypto_browser.mdx b/api_docs/kbn_crypto_browser.mdx index 5c73a9981b76c4..77788c27073dcd 100644 --- a/api_docs/kbn_crypto_browser.mdx +++ b/api_docs/kbn_crypto_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-crypto-browser title: "@kbn/crypto-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/crypto-browser plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto-browser'] --- import kbnCryptoBrowserObj from './kbn_crypto_browser.devdocs.json'; diff --git a/api_docs/kbn_datemath.mdx b/api_docs/kbn_datemath.mdx index cc1aaa0a7f76a7..669752ea179918 100644 --- a/api_docs/kbn_datemath.mdx +++ b/api_docs/kbn_datemath.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-datemath title: "@kbn/datemath" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/datemath plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/datemath'] --- import kbnDatemathObj from './kbn_datemath.devdocs.json'; diff --git a/api_docs/kbn_dev_cli_errors.mdx b/api_docs/kbn_dev_cli_errors.mdx index 53170339b30df7..653e1b5efe544b 100644 --- a/api_docs/kbn_dev_cli_errors.mdx +++ b/api_docs/kbn_dev_cli_errors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-cli-errors title: "@kbn/dev-cli-errors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-cli-errors plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-cli-errors'] --- import kbnDevCliErrorsObj from './kbn_dev_cli_errors.devdocs.json'; diff --git a/api_docs/kbn_dev_cli_runner.mdx b/api_docs/kbn_dev_cli_runner.mdx index c9ba13f62781da..f7edb115f49a9f 100644 --- a/api_docs/kbn_dev_cli_runner.mdx +++ b/api_docs/kbn_dev_cli_runner.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-cli-runner title: "@kbn/dev-cli-runner" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-cli-runner plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-cli-runner'] --- import kbnDevCliRunnerObj from './kbn_dev_cli_runner.devdocs.json'; diff --git a/api_docs/kbn_dev_proc_runner.mdx b/api_docs/kbn_dev_proc_runner.mdx index e6e3a5e84ba390..f83c97ef5f49d9 100644 --- a/api_docs/kbn_dev_proc_runner.mdx +++ b/api_docs/kbn_dev_proc_runner.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-proc-runner title: "@kbn/dev-proc-runner" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-proc-runner plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-proc-runner'] --- import kbnDevProcRunnerObj from './kbn_dev_proc_runner.devdocs.json'; diff --git a/api_docs/kbn_dev_utils.mdx b/api_docs/kbn_dev_utils.mdx index 964c46dd397ff9..7278c02638113f 100644 --- a/api_docs/kbn_dev_utils.mdx +++ b/api_docs/kbn_dev_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-utils title: "@kbn/dev-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-utils plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-utils'] --- import kbnDevUtilsObj from './kbn_dev_utils.devdocs.json'; diff --git a/api_docs/kbn_doc_links.devdocs.json b/api_docs/kbn_doc_links.devdocs.json index cf429b729b8076..4dcf21464cd010 100644 --- a/api_docs/kbn_doc_links.devdocs.json +++ b/api_docs/kbn_doc_links.devdocs.json @@ -300,7 +300,7 @@ "label": "enterpriseSearch", "description": [], "signature": [ - "{ readonly apiKeys: string; readonly bulkApi: string; readonly configuration: string; readonly connectors: string; readonly crawlerGettingStarted: string; readonly crawlerManaging: string; readonly crawlerOverview: string; readonly languageAnalyzers: string; readonly licenseManagement: string; readonly mailService: string; readonly start: string; readonly troubleshootSetup: string; readonly usersAccess: string; }" + "{ readonly apiKeys: string; readonly bulkApi: string; readonly configuration: string; readonly connectors: string; readonly crawlerGettingStarted: string; readonly crawlerManaging: string; readonly crawlerOverview: string; readonly languageAnalyzers: string; readonly languageClients: string; readonly licenseManagement: string; readonly mailService: string; readonly start: string; readonly troubleshootSetup: string; readonly usersAccess: string; }" ], "path": "packages/kbn-doc-links/src/types.ts", "deprecated": false, diff --git a/api_docs/kbn_doc_links.mdx b/api_docs/kbn_doc_links.mdx index 318be11d0b4be1..044c765674ea12 100644 --- a/api_docs/kbn_doc_links.mdx +++ b/api_docs/kbn_doc_links.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-doc-links title: "@kbn/doc-links" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/doc-links plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/doc-links'] --- import kbnDocLinksObj from './kbn_doc_links.devdocs.json'; diff --git a/api_docs/kbn_docs_utils.mdx b/api_docs/kbn_docs_utils.mdx index ea3c7f329c54dd..d47c4a94ac5345 100644 --- a/api_docs/kbn_docs_utils.mdx +++ b/api_docs/kbn_docs_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-docs-utils title: "@kbn/docs-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/docs-utils plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/docs-utils'] --- import kbnDocsUtilsObj from './kbn_docs_utils.devdocs.json'; diff --git a/api_docs/kbn_ebt_tools.mdx b/api_docs/kbn_ebt_tools.mdx index 80a62e78497f5f..5cc4b3d097f4ff 100644 --- a/api_docs/kbn_ebt_tools.mdx +++ b/api_docs/kbn_ebt_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ebt-tools title: "@kbn/ebt-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ebt-tools plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ebt-tools'] --- import kbnEbtToolsObj from './kbn_ebt_tools.devdocs.json'; diff --git a/api_docs/kbn_es_archiver.mdx b/api_docs/kbn_es_archiver.mdx index 7e7a2fc26faf18..5cad59a4b8f74d 100644 --- a/api_docs/kbn_es_archiver.mdx +++ b/api_docs/kbn_es_archiver.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-archiver title: "@kbn/es-archiver" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-archiver plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-archiver'] --- import kbnEsArchiverObj from './kbn_es_archiver.devdocs.json'; diff --git a/api_docs/kbn_es_errors.mdx b/api_docs/kbn_es_errors.mdx index c66768a2aa70e3..ca0ada58480340 100644 --- a/api_docs/kbn_es_errors.mdx +++ b/api_docs/kbn_es_errors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-errors title: "@kbn/es-errors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-errors plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-errors'] --- import kbnEsErrorsObj from './kbn_es_errors.devdocs.json'; diff --git a/api_docs/kbn_es_query.mdx b/api_docs/kbn_es_query.mdx index fbf8f231c74b88..792b606b4133a0 100644 --- a/api_docs/kbn_es_query.mdx +++ b/api_docs/kbn_es_query.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-query title: "@kbn/es-query" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-query plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-query'] --- import kbnEsQueryObj from './kbn_es_query.devdocs.json'; diff --git a/api_docs/kbn_eslint_plugin_imports.mdx b/api_docs/kbn_eslint_plugin_imports.mdx index 737f01b338245e..6e1eb7f3fcfde7 100644 --- a/api_docs/kbn_eslint_plugin_imports.mdx +++ b/api_docs/kbn_eslint_plugin_imports.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-eslint-plugin-imports title: "@kbn/eslint-plugin-imports" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/eslint-plugin-imports plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/eslint-plugin-imports'] --- import kbnEslintPluginImportsObj from './kbn_eslint_plugin_imports.devdocs.json'; diff --git a/api_docs/kbn_field_types.mdx b/api_docs/kbn_field_types.mdx index 4f006611e9fc33..3fa74decb5caac 100644 --- a/api_docs/kbn_field_types.mdx +++ b/api_docs/kbn_field_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-field-types title: "@kbn/field-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/field-types plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/field-types'] --- import kbnFieldTypesObj from './kbn_field_types.devdocs.json'; diff --git a/api_docs/kbn_find_used_node_modules.mdx b/api_docs/kbn_find_used_node_modules.mdx index 999bfe5e1ae729..5c3fcdaab984cb 100644 --- a/api_docs/kbn_find_used_node_modules.mdx +++ b/api_docs/kbn_find_used_node_modules.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-find-used-node-modules title: "@kbn/find-used-node-modules" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/find-used-node-modules plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/find-used-node-modules'] --- import kbnFindUsedNodeModulesObj from './kbn_find_used_node_modules.devdocs.json'; diff --git a/api_docs/kbn_generate.mdx b/api_docs/kbn_generate.mdx index 08ba76ffa10011..ed9435a3b3b748 100644 --- a/api_docs/kbn_generate.mdx +++ b/api_docs/kbn_generate.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-generate title: "@kbn/generate" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/generate plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate'] --- import kbnGenerateObj from './kbn_generate.devdocs.json'; diff --git a/api_docs/kbn_get_repo_files.mdx b/api_docs/kbn_get_repo_files.mdx index 0eb9adf03cae8f..3e663271b7a7d4 100644 --- a/api_docs/kbn_get_repo_files.mdx +++ b/api_docs/kbn_get_repo_files.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-get-repo-files title: "@kbn/get-repo-files" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/get-repo-files plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/get-repo-files'] --- import kbnGetRepoFilesObj from './kbn_get_repo_files.devdocs.json'; diff --git a/api_docs/kbn_handlebars.mdx b/api_docs/kbn_handlebars.mdx index f2548afb38b8fc..89013d791f80d2 100644 --- a/api_docs/kbn_handlebars.mdx +++ b/api_docs/kbn_handlebars.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-handlebars title: "@kbn/handlebars" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/handlebars plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/handlebars'] --- import kbnHandlebarsObj from './kbn_handlebars.devdocs.json'; diff --git a/api_docs/kbn_hapi_mocks.mdx b/api_docs/kbn_hapi_mocks.mdx index 71c5afc499e716..03c70dae79e772 100644 --- a/api_docs/kbn_hapi_mocks.mdx +++ b/api_docs/kbn_hapi_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-hapi-mocks title: "@kbn/hapi-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/hapi-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/hapi-mocks'] --- import kbnHapiMocksObj from './kbn_hapi_mocks.devdocs.json'; diff --git a/api_docs/kbn_home_sample_data_card.mdx b/api_docs/kbn_home_sample_data_card.mdx index fe9f7362f92d9a..4f6ed6ee570a8f 100644 --- a/api_docs/kbn_home_sample_data_card.mdx +++ b/api_docs/kbn_home_sample_data_card.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-home-sample-data-card title: "@kbn/home-sample-data-card" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/home-sample-data-card plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/home-sample-data-card'] --- import kbnHomeSampleDataCardObj from './kbn_home_sample_data_card.devdocs.json'; diff --git a/api_docs/kbn_home_sample_data_tab.mdx b/api_docs/kbn_home_sample_data_tab.mdx index 260ed51eb714a9..0d51ff6ce14658 100644 --- a/api_docs/kbn_home_sample_data_tab.mdx +++ b/api_docs/kbn_home_sample_data_tab.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-home-sample-data-tab title: "@kbn/home-sample-data-tab" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/home-sample-data-tab plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/home-sample-data-tab'] --- import kbnHomeSampleDataTabObj from './kbn_home_sample_data_tab.devdocs.json'; diff --git a/api_docs/kbn_i18n.mdx b/api_docs/kbn_i18n.mdx index 4831d49ebd44d9..dda867b946f49d 100644 --- a/api_docs/kbn_i18n.mdx +++ b/api_docs/kbn_i18n.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-i18n title: "@kbn/i18n" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/i18n plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/i18n'] --- import kbnI18nObj from './kbn_i18n.devdocs.json'; diff --git a/api_docs/kbn_import_resolver.mdx b/api_docs/kbn_import_resolver.mdx index 38cd87cb6c7d22..1eeda889c5cdd2 100644 --- a/api_docs/kbn_import_resolver.mdx +++ b/api_docs/kbn_import_resolver.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-import-resolver title: "@kbn/import-resolver" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/import-resolver plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/import-resolver'] --- import kbnImportResolverObj from './kbn_import_resolver.devdocs.json'; diff --git a/api_docs/kbn_interpreter.mdx b/api_docs/kbn_interpreter.mdx index 9165151e477f19..8c87bc7a914bd1 100644 --- a/api_docs/kbn_interpreter.mdx +++ b/api_docs/kbn_interpreter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-interpreter title: "@kbn/interpreter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/interpreter plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/interpreter'] --- import kbnInterpreterObj from './kbn_interpreter.devdocs.json'; diff --git a/api_docs/kbn_io_ts_utils.mdx b/api_docs/kbn_io_ts_utils.mdx index 28459bf26edb1b..1f89b3b7e535a0 100644 --- a/api_docs/kbn_io_ts_utils.mdx +++ b/api_docs/kbn_io_ts_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-io-ts-utils title: "@kbn/io-ts-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/io-ts-utils plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/io-ts-utils'] --- import kbnIoTsUtilsObj from './kbn_io_ts_utils.devdocs.json'; diff --git a/api_docs/kbn_jest_serializers.mdx b/api_docs/kbn_jest_serializers.mdx index ba94c00e027fef..6885069422ac0a 100644 --- a/api_docs/kbn_jest_serializers.mdx +++ b/api_docs/kbn_jest_serializers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-jest-serializers title: "@kbn/jest-serializers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/jest-serializers plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/jest-serializers'] --- import kbnJestSerializersObj from './kbn_jest_serializers.devdocs.json'; diff --git a/api_docs/kbn_kibana_manifest_parser.devdocs.json b/api_docs/kbn_kibana_manifest_parser.devdocs.json deleted file mode 100644 index 2a179421fb304a..00000000000000 --- a/api_docs/kbn_kibana_manifest_parser.devdocs.json +++ /dev/null @@ -1,174 +0,0 @@ -{ - "id": "@kbn/kibana-manifest-parser", - "client": { - "classes": [], - "functions": [], - "interfaces": [], - "enums": [], - "misc": [], - "objects": [] - }, - "server": { - "classes": [], - "functions": [ - { - "parentPluginId": "@kbn/kibana-manifest-parser", - "id": "def-server.parseKibanaManifest", - "type": "Function", - "tags": [], - "label": "parseKibanaManifest", - "description": [ - "\nParse a kibana.jsonc file from a string" - ], - "signature": [ - "(content: string) => ", - { - "pluginId": "@kbn/kibana-manifest-parser", - "scope": "server", - "docId": "kibKbnKibanaManifestParserPluginApi", - "section": "def-server.KibanaPackageManifest", - "text": "KibanaPackageManifest" - } - ], - "path": "packages/kbn-kibana-manifest-parser/src/parse_kibana_manifest.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "@kbn/kibana-manifest-parser", - "id": "def-server.parseKibanaManifest.$1", - "type": "string", - "tags": [], - "label": "content", - "description": [], - "signature": [ - "string" - ], - "path": "packages/kbn-kibana-manifest-parser/src/parse_kibana_manifest.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [], - "initialIsOpen": false - }, - { - "parentPluginId": "@kbn/kibana-manifest-parser", - "id": "def-server.readKibanaManifest", - "type": "Function", - "tags": [], - "label": "readKibanaManifest", - "description": [ - "\nParse a kibana.jsonc file from the filesystem" - ], - "signature": [ - "(path: string) => ", - { - "pluginId": "@kbn/kibana-manifest-parser", - "scope": "server", - "docId": "kibKbnKibanaManifestParserPluginApi", - "section": "def-server.KibanaPackageManifest", - "text": "KibanaPackageManifest" - } - ], - "path": "packages/kbn-kibana-manifest-parser/src/parse_kibana_manifest.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "@kbn/kibana-manifest-parser", - "id": "def-server.readKibanaManifest.$1", - "type": "string", - "tags": [], - "label": "path", - "description": [], - "signature": [ - "string" - ], - "path": "packages/kbn-kibana-manifest-parser/src/parse_kibana_manifest.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [], - "initialIsOpen": false - }, - { - "parentPluginId": "@kbn/kibana-manifest-parser", - "id": "def-server.validateKibanaManifest", - "type": "Function", - "tags": [], - "label": "validateKibanaManifest", - "description": [ - "\nValidate the contents of a parsed kibana.jsonc file." - ], - "signature": [ - "(parsed: unknown) => ", - { - "pluginId": "@kbn/kibana-manifest-parser", - "scope": "server", - "docId": "kibKbnKibanaManifestParserPluginApi", - "section": "def-server.KibanaPackageManifest", - "text": "KibanaPackageManifest" - } - ], - "path": "packages/kbn-kibana-manifest-parser/src/parse_kibana_manifest.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "@kbn/kibana-manifest-parser", - "id": "def-server.validateKibanaManifest.$1", - "type": "Unknown", - "tags": [], - "label": "parsed", - "description": [], - "signature": [ - "unknown" - ], - "path": "packages/kbn-kibana-manifest-parser/src/parse_kibana_manifest.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [], - "initialIsOpen": false - } - ], - "interfaces": [], - "enums": [], - "misc": [ - { - "parentPluginId": "@kbn/kibana-manifest-parser", - "id": "def-server.KibanaPackageManifest", - "type": "Type", - "tags": [], - "label": "KibanaPackageManifest", - "description": [], - "signature": [ - "PluginPackageManifest", - " | ", - "SharedBrowserPackageManifest", - " | ", - "BasePackageManifest" - ], - "path": "packages/kbn-kibana-manifest-parser/src/kibana_manifest.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - } - ], - "objects": [] - }, - "common": { - "classes": [], - "functions": [], - "interfaces": [], - "enums": [], - "misc": [], - "objects": [] - } -} \ No newline at end of file diff --git a/api_docs/kbn_kibana_manifest_parser.mdx b/api_docs/kbn_kibana_manifest_parser.mdx deleted file mode 100644 index 021c15b48ce902..00000000000000 --- a/api_docs/kbn_kibana_manifest_parser.mdx +++ /dev/null @@ -1,33 +0,0 @@ ---- -#### -#### This document is auto-generated and is meant to be viewed inside our experimental, new docs system. -#### Reach out in #docs-engineering for more info. -#### -id: kibKbnKibanaManifestParserPluginApi -slug: /kibana-dev-docs/api/kbn-kibana-manifest-parser -title: "@kbn/kibana-manifest-parser" -image: https://source.unsplash.com/400x175/?github -description: API docs for the @kbn/kibana-manifest-parser plugin -date: 2022-09-08 -tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/kibana-manifest-parser'] ---- -import kbnKibanaManifestParserObj from './kbn_kibana_manifest_parser.devdocs.json'; - - - -Contact [Owner missing] for questions regarding this plugin. - -**Code health stats** - -| Public API count | Any count | Items lacking comments | Missing exports | -|-------------------|-----------|------------------------|-----------------| -| 7 | 0 | 4 | 3 | - -## Server - -### Functions - - -### Consts, variables and types - - diff --git a/api_docs/kbn_kibana_manifest_schema.devdocs.json b/api_docs/kbn_kibana_manifest_schema.devdocs.json index 9a2294b16a387e..21bb0a106155f6 100644 --- a/api_docs/kbn_kibana_manifest_schema.devdocs.json +++ b/api_docs/kbn_kibana_manifest_schema.devdocs.json @@ -873,6 +873,19 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "@kbn/kibana-manifest-schema", + "id": "def-server.MANIFEST_V2.allowTrailingCommas", + "type": "boolean", + "tags": [], + "label": "allowTrailingCommas", + "description": [ + "// @ts-expect-error VSCode specific JSONSchema extension" + ], + "path": "packages/kbn-kibana-manifest-schema/src/kibana_json_v2_schema.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "@kbn/kibana-manifest-schema", "id": "def-server.MANIFEST_V2.properties", @@ -916,6 +929,17 @@ "path": "packages/kbn-kibana-manifest-schema/src/kibana_json_v2_schema.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "@kbn/kibana-manifest-schema", + "id": "def-server.MANIFEST_V2.properties.id.description", + "type": "string", + "tags": [], + "label": "description", + "description": [], + "path": "packages/kbn-kibana-manifest-schema/src/kibana_json_v2_schema.ts", + "deprecated": false, + "trackAdoption": false } ] }, @@ -967,10 +991,10 @@ }, { "parentPluginId": "@kbn/kibana-manifest-schema", - "id": "def-server.MANIFEST_V2.properties.typeDependencies", + "id": "def-server.MANIFEST_V2.properties.typeDeps", "type": "Object", "tags": [], - "label": "typeDependencies", + "label": "typeDeps", "description": [], "path": "packages/kbn-kibana-manifest-schema/src/kibana_json_v2_schema.ts", "deprecated": false, @@ -978,7 +1002,7 @@ "children": [ { "parentPluginId": "@kbn/kibana-manifest-schema", - "id": "def-server.MANIFEST_V2.properties.typeDependencies.type", + "id": "def-server.MANIFEST_V2.properties.typeDeps.type", "type": "string", "tags": [], "label": "type", @@ -989,7 +1013,7 @@ }, { "parentPluginId": "@kbn/kibana-manifest-schema", - "id": "def-server.MANIFEST_V2.properties.typeDependencies.description", + "id": "def-server.MANIFEST_V2.properties.typeDeps.description", "type": "string", "tags": [], "label": "description", @@ -1000,7 +1024,7 @@ }, { "parentPluginId": "@kbn/kibana-manifest-schema", - "id": "def-server.MANIFEST_V2.properties.typeDependencies.items", + "id": "def-server.MANIFEST_V2.properties.typeDeps.items", "type": "Object", "tags": [], "label": "items", @@ -1011,7 +1035,7 @@ "children": [ { "parentPluginId": "@kbn/kibana-manifest-schema", - "id": "def-server.MANIFEST_V2.properties.typeDependencies.items.type", + "id": "def-server.MANIFEST_V2.properties.typeDeps.items.type", "type": "string", "tags": [], "label": "type", @@ -1026,10 +1050,10 @@ }, { "parentPluginId": "@kbn/kibana-manifest-schema", - "id": "def-server.MANIFEST_V2.properties.runtimeDependencies", + "id": "def-server.MANIFEST_V2.properties.runtimeDeps", "type": "Object", "tags": [], - "label": "runtimeDependencies", + "label": "runtimeDeps", "description": [], "path": "packages/kbn-kibana-manifest-schema/src/kibana_json_v2_schema.ts", "deprecated": false, @@ -1037,7 +1061,7 @@ "children": [ { "parentPluginId": "@kbn/kibana-manifest-schema", - "id": "def-server.MANIFEST_V2.properties.runtimeDependencies.type", + "id": "def-server.MANIFEST_V2.properties.runtimeDeps.type", "type": "string", "tags": [], "label": "type", @@ -1048,7 +1072,7 @@ }, { "parentPluginId": "@kbn/kibana-manifest-schema", - "id": "def-server.MANIFEST_V2.properties.runtimeDependencies.description", + "id": "def-server.MANIFEST_V2.properties.runtimeDeps.description", "type": "string", "tags": [], "label": "description", @@ -1059,7 +1083,7 @@ }, { "parentPluginId": "@kbn/kibana-manifest-schema", - "id": "def-server.MANIFEST_V2.properties.runtimeDependencies.items", + "id": "def-server.MANIFEST_V2.properties.runtimeDeps.items", "type": "Object", "tags": [], "label": "items", @@ -1070,7 +1094,7 @@ "children": [ { "parentPluginId": "@kbn/kibana-manifest-schema", - "id": "def-server.MANIFEST_V2.properties.runtimeDependencies.items.type", + "id": "def-server.MANIFEST_V2.properties.runtimeDeps.items.type", "type": "string", "tags": [], "label": "type", @@ -1082,6 +1106,52 @@ ] } ] + }, + { + "parentPluginId": "@kbn/kibana-manifest-schema", + "id": "def-server.MANIFEST_V2.properties.devOnly", + "type": "Object", + "tags": [], + "label": "devOnly", + "description": [], + "path": "packages/kbn-kibana-manifest-schema/src/kibana_json_v2_schema.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/kibana-manifest-schema", + "id": "def-server.MANIFEST_V2.properties.devOnly.type", + "type": "string", + "tags": [], + "label": "type", + "description": [], + "path": "packages/kbn-kibana-manifest-schema/src/kibana_json_v2_schema.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/kibana-manifest-schema", + "id": "def-server.MANIFEST_V2.properties.devOnly.description", + "type": "string", + "tags": [], + "label": "description", + "description": [], + "path": "packages/kbn-kibana-manifest-schema/src/kibana_json_v2_schema.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/kibana-manifest-schema", + "id": "def-server.MANIFEST_V2.properties.devOnly.default", + "type": "boolean", + "tags": [], + "label": "default", + "description": [], + "path": "packages/kbn-kibana-manifest-schema/src/kibana_json_v2_schema.ts", + "deprecated": false, + "trackAdoption": false + } + ] } ] }, diff --git a/api_docs/kbn_kibana_manifest_schema.mdx b/api_docs/kbn_kibana_manifest_schema.mdx index ec3e2af47fc8f0..771d6d1341fcaf 100644 --- a/api_docs/kbn_kibana_manifest_schema.mdx +++ b/api_docs/kbn_kibana_manifest_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-kibana-manifest-schema title: "@kbn/kibana-manifest-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/kibana-manifest-schema plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/kibana-manifest-schema'] --- import kbnKibanaManifestSchemaObj from './kbn_kibana_manifest_schema.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Owner missing] for questions regarding this plugin. | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 91 | 0 | 91 | 0 | +| 97 | 0 | 96 | 0 | ## Server diff --git a/api_docs/kbn_logging.mdx b/api_docs/kbn_logging.mdx index e09b62c0bb1b97..eb7eb96ae58c22 100644 --- a/api_docs/kbn_logging.mdx +++ b/api_docs/kbn_logging.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-logging title: "@kbn/logging" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/logging plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/logging'] --- import kbnLoggingObj from './kbn_logging.devdocs.json'; diff --git a/api_docs/kbn_logging_mocks.mdx b/api_docs/kbn_logging_mocks.mdx index c0923437c7df59..c778ebc86da322 100644 --- a/api_docs/kbn_logging_mocks.mdx +++ b/api_docs/kbn_logging_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-logging-mocks title: "@kbn/logging-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/logging-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/logging-mocks'] --- import kbnLoggingMocksObj from './kbn_logging_mocks.devdocs.json'; diff --git a/api_docs/kbn_managed_vscode_config.mdx b/api_docs/kbn_managed_vscode_config.mdx index 5e5e690c99883f..f9799e1ac39470 100644 --- a/api_docs/kbn_managed_vscode_config.mdx +++ b/api_docs/kbn_managed_vscode_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-managed-vscode-config title: "@kbn/managed-vscode-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/managed-vscode-config plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/managed-vscode-config'] --- import kbnManagedVscodeConfigObj from './kbn_managed_vscode_config.devdocs.json'; diff --git a/api_docs/kbn_mapbox_gl.mdx b/api_docs/kbn_mapbox_gl.mdx index 7977d526471577..fc653bed6e7e95 100644 --- a/api_docs/kbn_mapbox_gl.mdx +++ b/api_docs/kbn_mapbox_gl.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-mapbox-gl title: "@kbn/mapbox-gl" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/mapbox-gl plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/mapbox-gl'] --- import kbnMapboxGlObj from './kbn_mapbox_gl.devdocs.json'; diff --git a/api_docs/kbn_ml_agg_utils.mdx b/api_docs/kbn_ml_agg_utils.mdx index ff08f4cbbad11d..12b0ecb60e66ca 100644 --- a/api_docs/kbn_ml_agg_utils.mdx +++ b/api_docs/kbn_ml_agg_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-agg-utils title: "@kbn/ml-agg-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-agg-utils plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-agg-utils'] --- import kbnMlAggUtilsObj from './kbn_ml_agg_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_is_populated_object.mdx b/api_docs/kbn_ml_is_populated_object.mdx index 36546dca936960..67f7ef712b4190 100644 --- a/api_docs/kbn_ml_is_populated_object.mdx +++ b/api_docs/kbn_ml_is_populated_object.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-is-populated-object title: "@kbn/ml-is-populated-object" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-is-populated-object plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-is-populated-object'] --- import kbnMlIsPopulatedObjectObj from './kbn_ml_is_populated_object.devdocs.json'; diff --git a/api_docs/kbn_ml_string_hash.mdx b/api_docs/kbn_ml_string_hash.mdx index 5db7b02795897d..a8aa07a6cb0ad5 100644 --- a/api_docs/kbn_ml_string_hash.mdx +++ b/api_docs/kbn_ml_string_hash.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-string-hash title: "@kbn/ml-string-hash" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-string-hash plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-string-hash'] --- import kbnMlStringHashObj from './kbn_ml_string_hash.devdocs.json'; diff --git a/api_docs/kbn_monaco.mdx b/api_docs/kbn_monaco.mdx index ff8408aff7acc8..cf5344b7847eba 100644 --- a/api_docs/kbn_monaco.mdx +++ b/api_docs/kbn_monaco.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-monaco title: "@kbn/monaco" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/monaco plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/monaco'] --- import kbnMonacoObj from './kbn_monaco.devdocs.json'; diff --git a/api_docs/kbn_optimizer.mdx b/api_docs/kbn_optimizer.mdx index de2ba0f075c74b..59384f2ce9406d 100644 --- a/api_docs/kbn_optimizer.mdx +++ b/api_docs/kbn_optimizer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-optimizer title: "@kbn/optimizer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/optimizer plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/optimizer'] --- import kbnOptimizerObj from './kbn_optimizer.devdocs.json'; diff --git a/api_docs/kbn_optimizer_webpack_helpers.mdx b/api_docs/kbn_optimizer_webpack_helpers.mdx index 8fe04c2d25f157..cb5c6845f2d4f4 100644 --- a/api_docs/kbn_optimizer_webpack_helpers.mdx +++ b/api_docs/kbn_optimizer_webpack_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-optimizer-webpack-helpers title: "@kbn/optimizer-webpack-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/optimizer-webpack-helpers plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/optimizer-webpack-helpers'] --- import kbnOptimizerWebpackHelpersObj from './kbn_optimizer_webpack_helpers.devdocs.json'; diff --git a/api_docs/kbn_performance_testing_dataset_extractor.mdx b/api_docs/kbn_performance_testing_dataset_extractor.mdx index aa1371dd75ae41..2445802229bf1d 100644 --- a/api_docs/kbn_performance_testing_dataset_extractor.mdx +++ b/api_docs/kbn_performance_testing_dataset_extractor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-performance-testing-dataset-extractor title: "@kbn/performance-testing-dataset-extractor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/performance-testing-dataset-extractor plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/performance-testing-dataset-extractor'] --- import kbnPerformanceTestingDatasetExtractorObj from './kbn_performance_testing_dataset_extractor.devdocs.json'; diff --git a/api_docs/kbn_plugin_generator.mdx b/api_docs/kbn_plugin_generator.mdx index 8fcbf064242d96..617d5fec736bf8 100644 --- a/api_docs/kbn_plugin_generator.mdx +++ b/api_docs/kbn_plugin_generator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-generator title: "@kbn/plugin-generator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/plugin-generator plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-generator'] --- import kbnPluginGeneratorObj from './kbn_plugin_generator.devdocs.json'; diff --git a/api_docs/kbn_plugin_helpers.mdx b/api_docs/kbn_plugin_helpers.mdx index d40aceba8e1d40..44df77707e11de 100644 --- a/api_docs/kbn_plugin_helpers.mdx +++ b/api_docs/kbn_plugin_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-helpers title: "@kbn/plugin-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/plugin-helpers plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-helpers'] --- import kbnPluginHelpersObj from './kbn_plugin_helpers.devdocs.json'; diff --git a/api_docs/kbn_react_field.mdx b/api_docs/kbn_react_field.mdx index df6f561e8cda64..6917f3fc99b3ba 100644 --- a/api_docs/kbn_react_field.mdx +++ b/api_docs/kbn_react_field.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-field title: "@kbn/react-field" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-field plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-field'] --- import kbnReactFieldObj from './kbn_react_field.devdocs.json'; diff --git a/api_docs/kbn_repo_source_classifier.mdx b/api_docs/kbn_repo_source_classifier.mdx index 701d2b801f102b..9b30733e7280b3 100644 --- a/api_docs/kbn_repo_source_classifier.mdx +++ b/api_docs/kbn_repo_source_classifier.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-source-classifier title: "@kbn/repo-source-classifier" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-source-classifier plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-source-classifier'] --- import kbnRepoSourceClassifierObj from './kbn_repo_source_classifier.devdocs.json'; diff --git a/api_docs/kbn_rule_data_utils.mdx b/api_docs/kbn_rule_data_utils.mdx index 25cd1e62b3ecb2..d278bd47a83cc6 100644 --- a/api_docs/kbn_rule_data_utils.mdx +++ b/api_docs/kbn_rule_data_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rule-data-utils title: "@kbn/rule-data-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rule-data-utils plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rule-data-utils'] --- import kbnRuleDataUtilsObj from './kbn_rule_data_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_autocomplete.mdx b/api_docs/kbn_securitysolution_autocomplete.mdx index 69baed8fab2fd4..e1c8c47ea5d192 100644 --- a/api_docs/kbn_securitysolution_autocomplete.mdx +++ b/api_docs/kbn_securitysolution_autocomplete.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-autocomplete title: "@kbn/securitysolution-autocomplete" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-autocomplete plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-autocomplete'] --- import kbnSecuritysolutionAutocompleteObj from './kbn_securitysolution_autocomplete.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_es_utils.mdx b/api_docs/kbn_securitysolution_es_utils.mdx index 8694ba391c1dff..d2a1be19c6c177 100644 --- a/api_docs/kbn_securitysolution_es_utils.mdx +++ b/api_docs/kbn_securitysolution_es_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-es-utils title: "@kbn/securitysolution-es-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-es-utils plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-es-utils'] --- import kbnSecuritysolutionEsUtilsObj from './kbn_securitysolution_es_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_hook_utils.mdx b/api_docs/kbn_securitysolution_hook_utils.mdx index 679a6d384fd0d9..e4fbf89a1405f1 100644 --- a/api_docs/kbn_securitysolution_hook_utils.mdx +++ b/api_docs/kbn_securitysolution_hook_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-hook-utils title: "@kbn/securitysolution-hook-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-hook-utils plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-hook-utils'] --- import kbnSecuritysolutionHookUtilsObj from './kbn_securitysolution_hook_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx b/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx index 3e7bae71056d5f..38f823267cd07d 100644 --- a/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-alerting-types title: "@kbn/securitysolution-io-ts-alerting-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-alerting-types plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-alerting-types'] --- import kbnSecuritysolutionIoTsAlertingTypesObj from './kbn_securitysolution_io_ts_alerting_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_list_types.devdocs.json b/api_docs/kbn_securitysolution_io_ts_list_types.devdocs.json index 027cbb793cc9f6..f75157365c8830 100644 --- a/api_docs/kbn_securitysolution_io_ts_list_types.devdocs.json +++ b/api_docs/kbn_securitysolution_io_ts_list_types.devdocs.json @@ -363,20 +363,13 @@ }, { "parentPluginId": "@kbn/securitysolution-io-ts-list-types", - "id": "def-common.ApiCallByListIdProps.filterOptions", - "type": "Array", + "id": "def-common.ApiCallByListIdProps.pagination", + "type": "Object", "tags": [], - "label": "filterOptions", + "label": "pagination", "description": [], "signature": [ - { - "pluginId": "@kbn/securitysolution-io-ts-list-types", - "scope": "common", - "docId": "kibKbnSecuritysolutionIoTsListTypesPluginApi", - "section": "def-common.FilterExceptionsOptions", - "text": "FilterExceptionsOptions" - }, - "[]" + "{ page?: number | undefined; perPage?: number | undefined; total?: number | undefined; }" ], "path": "packages/kbn-securitysolution-io-ts-list-types/src/typescript_types/index.ts", "deprecated": false, @@ -384,13 +377,27 @@ }, { "parentPluginId": "@kbn/securitysolution-io-ts-list-types", - "id": "def-common.ApiCallByListIdProps.pagination", - "type": "Object", + "id": "def-common.ApiCallByListIdProps.search", + "type": "string", "tags": [], - "label": "pagination", + "label": "search", "description": [], "signature": [ - "{ page?: number | undefined; perPage?: number | undefined; total?: number | undefined; }" + "string | undefined" + ], + "path": "packages/kbn-securitysolution-io-ts-list-types/src/typescript_types/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/securitysolution-io-ts-list-types", + "id": "def-common.ApiCallByListIdProps.filter", + "type": "string", + "tags": [], + "label": "filter", + "description": [], + "signature": [ + "string | undefined" ], "path": "packages/kbn-securitysolution-io-ts-list-types/src/typescript_types/index.ts", "deprecated": false, @@ -523,27 +530,6 @@ "deprecated": false, "trackAdoption": false }, - { - "parentPluginId": "@kbn/securitysolution-io-ts-list-types", - "id": "def-common.ApiCallFindListsItemsMemoProps.filterOptions", - "type": "Array", - "tags": [], - "label": "filterOptions", - "description": [], - "signature": [ - { - "pluginId": "@kbn/securitysolution-io-ts-list-types", - "scope": "common", - "docId": "kibKbnSecuritysolutionIoTsListTypesPluginApi", - "section": "def-common.FilterExceptionsOptions", - "text": "FilterExceptionsOptions" - }, - "[]" - ], - "path": "packages/kbn-securitysolution-io-ts-list-types/src/typescript_types/index.ts", - "deprecated": false, - "trackAdoption": false - }, { "parentPluginId": "@kbn/securitysolution-io-ts-list-types", "id": "def-common.ApiCallFindListsItemsMemoProps.pagination", @@ -580,6 +566,20 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "@kbn/securitysolution-io-ts-list-types", + "id": "def-common.ApiCallFindListsItemsMemoProps.filter", + "type": "string", + "tags": [], + "label": "filter", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-securitysolution-io-ts-list-types/src/typescript_types/index.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "@kbn/securitysolution-io-ts-list-types", "id": "def-common.ApiCallFindListsItemsMemoProps.onError", @@ -2873,7 +2873,7 @@ "label": "FindExceptionListItemSchema", "description": [], "signature": [ - "{ list_id: string; } & { filter?: string | null | undefined; namespace_type?: string | null | undefined; page?: string | undefined; per_page?: string | undefined; sort_field?: string | undefined; sort_order?: \"asc\" | \"desc\" | undefined; }" + "{ list_id: string; } & { filter?: string | null | undefined; namespace_type?: string | null | undefined; page?: string | undefined; per_page?: string | undefined; search?: string | undefined; sort_field?: string | undefined; sort_order?: \"asc\" | \"desc\" | undefined; }" ], "path": "packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_item_schema/index.ts", "deprecated": false, @@ -2888,7 +2888,7 @@ "label": "FindExceptionListItemSchemaDecoded", "description": [], "signature": [ - "Omit<{ list_id: string[]; filter: string[] | undefined; namespace_type: (\"single\" | \"agnostic\")[] | undefined; page: number | undefined; per_page: number | undefined; sort_field: string | undefined; sort_order: \"asc\" | \"desc\" | undefined; }, \"filter\" | \"namespace_type\"> & { filter: string[]; namespace_type: (\"single\" | \"agnostic\")[]; }" + "Omit<{ list_id: string[]; filter: string[] | undefined; namespace_type: (\"single\" | \"agnostic\")[] | undefined; page: number | undefined; per_page: number | undefined; search: string | undefined; sort_field: string | undefined; sort_order: \"asc\" | \"desc\" | undefined; }, \"filter\" | \"namespace_type\"> & { filter: string[]; namespace_type: (\"single\" | \"agnostic\")[]; }" ], "path": "packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_item_schema/index.ts", "deprecated": false, @@ -3285,6 +3285,36 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/securitysolution-io-ts-list-types", + "id": "def-common.InternalCreateExceptionListSchema", + "type": "Type", + "tags": [], + "label": "InternalCreateExceptionListSchema", + "description": [], + "signature": [ + "{ type: \"endpoint\" | \"endpoint_events\" | \"endpoint_host_isolation_exceptions\" | \"endpoint_blocklists\"; } & { list_id?: \"endpoint_trusted_apps\" | \"endpoint_event_filters\" | \"endpoint_host_isolation_exceptions\" | \"endpoint_blocklists\" | undefined; } & { description: string; name: string; type: \"endpoint\" | \"detection\" | \"rule_default\" | \"endpoint_trusted_apps\" | \"endpoint_events\" | \"endpoint_host_isolation_exceptions\" | \"endpoint_blocklists\"; } & { list_id?: string | undefined; meta?: object | undefined; namespace_type?: \"single\" | \"agnostic\" | undefined; os_types?: (\"windows\" | \"linux\" | \"macos\")[] | undefined; tags?: string[] | undefined; version?: number | undefined; }" + ], + "path": "packages/kbn-securitysolution-io-ts-list-types/src/request/internal/create_exception_list_schema/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/securitysolution-io-ts-list-types", + "id": "def-common.InternalCreateExceptionListSchemaDecoded", + "type": "Type", + "tags": [], + "label": "InternalCreateExceptionListSchemaDecoded", + "description": [], + "signature": [ + "Omit<{ description: string; name: string; type: \"endpoint\" | \"detection\" | \"rule_default\" | \"endpoint_trusted_apps\" | \"endpoint_events\" | \"endpoint_host_isolation_exceptions\" | \"endpoint_blocklists\"; list_id: string | undefined; meta: object | undefined; namespace_type: \"single\" | \"agnostic\" | undefined; os_types: (\"windows\" | \"linux\" | \"macos\")[] | undefined; tags: string[] | undefined; version: number | undefined; }, \"tags\" | \"list_id\" | \"namespace_type\" | \"os_types\"> & { tags: string[]; list_id: string; namespace_type: \"single\" | \"agnostic\"; os_types: (\"windows\" | \"linux\" | \"macos\")[]; version: number; }" + ], + "path": "packages/kbn-securitysolution-io-ts-list-types/src/request/internal/create_exception_list_schema/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/securitysolution-io-ts-list-types", "id": "def-common.ItemId", @@ -4095,6 +4125,21 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/securitysolution-io-ts-list-types", + "id": "def-common.Search", + "type": "Type", + "tags": [], + "label": "Search", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-securitysolution-io-ts-list-types/src/common/search/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/securitysolution-io-ts-list-types", "id": "def-common.SearchAfter", @@ -4155,6 +4200,21 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/securitysolution-io-ts-list-types", + "id": "def-common.SearchOrUndefined", + "type": "Type", + "tags": [], + "label": "SearchOrUndefined", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-securitysolution-io-ts-list-types/src/common/search/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/securitysolution-io-ts-list-types", "id": "def-common.Serializer", @@ -6641,6 +6701,8 @@ "StringToPositiveNumberC", "; per_page: ", "StringToPositiveNumberC", + "; search: ", + "StringC", "; sort_field: ", "StringC", "; sort_order: ", @@ -7603,6 +7665,66 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/securitysolution-io-ts-list-types", + "id": "def-common.internalCreateExceptionListSchema", + "type": "Object", + "tags": [], + "label": "internalCreateExceptionListSchema", + "description": [], + "signature": [ + "IntersectionC", + "<[", + "ExactC", + "<", + "TypeC", + "<{ type: ", + "KeyofC", + "<{ endpoint: null; endpoint_events: null; endpoint_host_isolation_exceptions: null; endpoint_blocklists: null; }>; }>>, ", + "ExactC", + "<", + "PartialC", + "<{ list_id: ", + "KeyofC", + "<{ endpoint_trusted_apps: null; endpoint_event_filters: null; endpoint_host_isolation_exceptions: null; endpoint_blocklists: null; }>; }>>, ", + "IntersectionC", + "<[", + "ExactC", + "<", + "TypeC", + "<{ description: ", + "StringC", + "; name: ", + "StringC", + "; type: ", + "KeyofC", + "<{ detection: null; rule_default: null; endpoint: null; endpoint_trusted_apps: null; endpoint_events: null; endpoint_host_isolation_exceptions: null; endpoint_blocklists: null; }>; }>>, ", + "ExactC", + "<", + "PartialC", + "<{ list_id: ", + "Type", + "; meta: ", + "ObjectC", + "; namespace_type: ", + "Type", + "<\"single\" | \"agnostic\", \"single\" | \"agnostic\" | undefined, unknown>; os_types: ", + "UnionC", + "<[", + "Type", + "<(\"windows\" | \"linux\" | \"macos\")[], (\"windows\" | \"linux\" | \"macos\")[] | undefined, unknown>, ", + "UndefinedC", + "]>; tags: ", + "Type", + "; version: ", + "Type", + "; }>>]>]>" + ], + "path": "packages/kbn-securitysolution-io-ts-list-types/src/request/internal/create_exception_list_schema/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/securitysolution-io-ts-list-types", "id": "def-common.item_id", @@ -8756,6 +8878,21 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/securitysolution-io-ts-list-types", + "id": "def-common.search", + "type": "Object", + "tags": [], + "label": "search", + "description": [], + "signature": [ + "StringC" + ], + "path": "packages/kbn-securitysolution-io-ts-list-types/src/common/search/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/securitysolution-io-ts-list-types", "id": "def-common.search_after", @@ -8936,6 +9073,26 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/securitysolution-io-ts-list-types", + "id": "def-common.searchOrUndefined", + "type": "Object", + "tags": [], + "label": "searchOrUndefined", + "description": [], + "signature": [ + "UnionC", + "<[", + "StringC", + ", ", + "UndefinedC", + "]>" + ], + "path": "packages/kbn-securitysolution-io-ts-list-types/src/common/search/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/securitysolution-io-ts-list-types", "id": "def-common.serializer", diff --git a/api_docs/kbn_securitysolution_io_ts_list_types.mdx b/api_docs/kbn_securitysolution_io_ts_list_types.mdx index fb03b23a345c5b..adec0fb8b5efb8 100644 --- a/api_docs/kbn_securitysolution_io_ts_list_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_list_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-list-types title: "@kbn/securitysolution-io-ts-list-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-list-types plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-list-types'] --- import kbnSecuritysolutionIoTsListTypesObj from './kbn_securitysolution_io_ts_list_types.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Owner missing] for questions regarding this plugin. | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 462 | 1 | 449 | 0 | +| 470 | 1 | 457 | 0 | ## Common diff --git a/api_docs/kbn_securitysolution_io_ts_types.mdx b/api_docs/kbn_securitysolution_io_ts_types.mdx index e15f7b18725a20..cf020e8b0a27ae 100644 --- a/api_docs/kbn_securitysolution_io_ts_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-types title: "@kbn/securitysolution-io-ts-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-types plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-types'] --- import kbnSecuritysolutionIoTsTypesObj from './kbn_securitysolution_io_ts_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_utils.mdx b/api_docs/kbn_securitysolution_io_ts_utils.mdx index 4846fce79df38d..598a866af57e8a 100644 --- a/api_docs/kbn_securitysolution_io_ts_utils.mdx +++ b/api_docs/kbn_securitysolution_io_ts_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-utils title: "@kbn/securitysolution-io-ts-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-utils plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-utils'] --- import kbnSecuritysolutionIoTsUtilsObj from './kbn_securitysolution_io_ts_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_api.devdocs.json b/api_docs/kbn_securitysolution_list_api.devdocs.json index 5f064750947763..2f92e25cf8befe 100644 --- a/api_docs/kbn_securitysolution_list_api.devdocs.json +++ b/api_docs/kbn_securitysolution_list_api.devdocs.json @@ -452,7 +452,7 @@ "label": "fetchExceptionListsItemsByListIdsWithValidation", "description": [], "signature": [ - "({ filterOptions, http, listIds, namespaceTypes, pagination, signal, }: ", + "({ filter, http, listIds, namespaceTypes, pagination, search, signal, }: ", "ApiCallByListIdProps", ") => Promise<{ data: { _version: string | undefined; comments: ({ comment: string; created_at: string; created_by: string; id: string; } & { updated_at?: string | undefined; updated_by?: string | undefined; })[]; created_at: string; created_by: string; description: string; entries: ({ field: string; operator: \"excluded\" | \"included\"; type: \"match\"; value: string; } | { field: string; operator: \"excluded\" | \"included\"; type: \"match_any\"; value: string[]; } | { field: string; list: { id: string; type: \"boolean\" | \"date\" | \"keyword\" | \"ip\" | \"text\" | \"geo_point\" | \"geo_shape\" | \"date_nanos\" | \"long\" | \"double\" | \"date_range\" | \"ip_range\" | \"shape\" | \"short\" | \"binary\" | \"float\" | \"half_float\" | \"integer\" | \"byte\" | \"long_range\" | \"integer_range\" | \"float_range\" | \"double_range\"; }; operator: \"excluded\" | \"included\"; type: \"list\"; } | { field: string; operator: \"excluded\" | \"included\"; type: \"exists\"; } | { entries: ({ field: string; operator: \"excluded\" | \"included\"; type: \"exists\"; } | { field: string; operator: \"excluded\" | \"included\"; type: \"match\"; value: string; } | { field: string; operator: \"excluded\" | \"included\"; type: \"match_any\"; value: string[]; })[]; field: string; type: \"nested\"; } | { field: string; operator: \"excluded\" | \"included\"; type: \"wildcard\"; value: string; })[]; id: string; item_id: string; list_id: string; meta: object | undefined; name: string; namespace_type: \"single\" | \"agnostic\"; os_types: (\"windows\" | \"linux\" | \"macos\")[]; tags: string[]; tie_breaker_id: string; type: \"simple\"; updated_at: string; updated_by: string; }[]; page: number; per_page: number; total: number; } & { pit?: string | undefined; }>" ], @@ -465,7 +465,7 @@ "id": "def-common.fetchExceptionListsItemsByListIdsWithValidation.$1", "type": "Object", "tags": [], - "label": "{\n filterOptions,\n http,\n listIds,\n namespaceTypes,\n pagination,\n signal,\n}", + "label": "{\n filter,\n http,\n listIds,\n namespaceTypes,\n pagination,\n search,\n signal,\n}", "description": [], "signature": [ "ApiCallByListIdProps" diff --git a/api_docs/kbn_securitysolution_list_api.mdx b/api_docs/kbn_securitysolution_list_api.mdx index fcec313dc1700c..7f8c8c61107518 100644 --- a/api_docs/kbn_securitysolution_list_api.mdx +++ b/api_docs/kbn_securitysolution_list_api.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-api title: "@kbn/securitysolution-list-api" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-api plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-api'] --- import kbnSecuritysolutionListApiObj from './kbn_securitysolution_list_api.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_constants.devdocs.json b/api_docs/kbn_securitysolution_list_constants.devdocs.json index a4ec4fcc115c19..3b2c4d28235099 100644 --- a/api_docs/kbn_securitysolution_list_constants.devdocs.json +++ b/api_docs/kbn_securitysolution_list_constants.devdocs.json @@ -363,6 +363,32 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/securitysolution-list-constants", + "id": "def-common.INTERNAL_EXCEPTION_LIST_URL", + "type": "string", + "tags": [], + "label": "INTERNAL_EXCEPTION_LIST_URL", + "description": [ + "\nInternal exception list routes" + ], + "path": "packages/kbn-securitysolution-list-constants/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/securitysolution-list-constants", + "id": "def-common.INTERNAL_EXCEPTIONS_LIST_ENSURE_CREATED_URL", + "type": "string", + "tags": [], + "label": "INTERNAL_EXCEPTIONS_LIST_ENSURE_CREATED_URL", + "description": [], + "path": "packages/kbn-securitysolution-list-constants/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/securitysolution-list-constants", "id": "def-common.LIST_INDEX", diff --git a/api_docs/kbn_securitysolution_list_constants.mdx b/api_docs/kbn_securitysolution_list_constants.mdx index 352154a93c5566..3690bc8cbc2b4c 100644 --- a/api_docs/kbn_securitysolution_list_constants.mdx +++ b/api_docs/kbn_securitysolution_list_constants.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-constants title: "@kbn/securitysolution-list-constants" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-constants plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-constants'] --- import kbnSecuritysolutionListConstantsObj from './kbn_securitysolution_list_constants.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Owner missing] for questions regarding this plugin. | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 26 | 0 | 12 | 0 | +| 28 | 0 | 13 | 0 | ## Common diff --git a/api_docs/kbn_securitysolution_list_hooks.devdocs.json b/api_docs/kbn_securitysolution_list_hooks.devdocs.json index ed317805a036b3..05d6b763b7c163 100644 --- a/api_docs/kbn_securitysolution_list_hooks.devdocs.json +++ b/api_docs/kbn_securitysolution_list_hooks.devdocs.json @@ -341,50 +341,6 @@ "returnComment": [], "initialIsOpen": false }, - { - "parentPluginId": "@kbn/securitysolution-list-hooks", - "id": "def-common.useExceptionListItems", - "type": "Function", - "tags": [], - "label": "useExceptionListItems", - "description": [ - "\nHook for using to get an ExceptionList and its ExceptionListItems\n" - ], - "signature": [ - "({ http, lists, pagination, filterOptions, showDetectionsListsOnly, showEndpointListsOnly, matchFilters, onError, onSuccess, }: ", - "UseExceptionListProps", - ") => ", - { - "pluginId": "@kbn/securitysolution-list-hooks", - "scope": "common", - "docId": "kibKbnSecuritysolutionListHooksPluginApi", - "section": "def-common.ReturnExceptionListAndItems", - "text": "ReturnExceptionListAndItems" - } - ], - "path": "packages/kbn-securitysolution-list-hooks/src/use_exception_list_items/index.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "@kbn/securitysolution-list-hooks", - "id": "def-common.useExceptionListItems.$1", - "type": "Object", - "tags": [], - "label": "{\n http,\n lists,\n pagination = {\n page: 1,\n perPage: 20,\n total: 0,\n },\n filterOptions,\n showDetectionsListsOnly,\n showEndpointListsOnly,\n matchFilters,\n onError,\n onSuccess,\n}", - "description": [], - "signature": [ - "UseExceptionListProps" - ], - "path": "packages/kbn-securitysolution-list-hooks/src/use_exception_list_items/index.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [], - "initialIsOpen": false - }, { "parentPluginId": "@kbn/securitysolution-list-hooks", "id": "def-common.useExceptionLists", @@ -998,23 +954,6 @@ "children": [], "initialIsOpen": false }, - { - "parentPluginId": "@kbn/securitysolution-list-hooks", - "id": "def-common.ReturnExceptionListAndItems", - "type": "Type", - "tags": [], - "label": "ReturnExceptionListAndItems", - "description": [], - "signature": [ - "[boolean, { _version: string | undefined; comments: ({ comment: string; created_at: string; created_by: string; id: string; } & { updated_at?: string | undefined; updated_by?: string | undefined; })[]; created_at: string; created_by: string; description: string; entries: ({ field: string; operator: \"excluded\" | \"included\"; type: \"match\"; value: string; } | { field: string; operator: \"excluded\" | \"included\"; type: \"match_any\"; value: string[]; } | { field: string; list: { id: string; type: \"boolean\" | \"date\" | \"keyword\" | \"ip\" | \"text\" | \"geo_point\" | \"geo_shape\" | \"date_nanos\" | \"long\" | \"double\" | \"date_range\" | \"ip_range\" | \"shape\" | \"short\" | \"binary\" | \"float\" | \"half_float\" | \"integer\" | \"byte\" | \"long_range\" | \"integer_range\" | \"float_range\" | \"double_range\"; }; operator: \"excluded\" | \"included\"; type: \"list\"; } | { field: string; operator: \"excluded\" | \"included\"; type: \"exists\"; } | { entries: ({ field: string; operator: \"excluded\" | \"included\"; type: \"exists\"; } | { field: string; operator: \"excluded\" | \"included\"; type: \"match\"; value: string; } | { field: string; operator: \"excluded\" | \"included\"; type: \"match_any\"; value: string[]; })[]; field: string; type: \"nested\"; } | { field: string; operator: \"excluded\" | \"included\"; type: \"wildcard\"; value: string; })[]; id: string; item_id: string; list_id: string; meta: object | undefined; name: string; namespace_type: \"single\" | \"agnostic\"; os_types: (\"windows\" | \"linux\" | \"macos\")[]; tags: string[]; tie_breaker_id: string; type: \"simple\"; updated_at: string; updated_by: string; }[], ", - "Pagination", - ", Func | null]" - ], - "path": "packages/kbn-securitysolution-list-hooks/src/use_exception_list_items/index.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, { "parentPluginId": "@kbn/securitysolution-list-hooks", "id": "def-common.ReturnExceptionLists", diff --git a/api_docs/kbn_securitysolution_list_hooks.mdx b/api_docs/kbn_securitysolution_list_hooks.mdx index 8792a1d797618b..e30499cbbf39a5 100644 --- a/api_docs/kbn_securitysolution_list_hooks.mdx +++ b/api_docs/kbn_securitysolution_list_hooks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-hooks title: "@kbn/securitysolution-list-hooks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-hooks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-hooks'] --- import kbnSecuritysolutionListHooksObj from './kbn_securitysolution_list_hooks.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Owner missing] for questions regarding this plugin. | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 56 | 0 | 44 | 0 | +| 53 | 0 | 42 | 0 | ## Common diff --git a/api_docs/kbn_securitysolution_list_utils.mdx b/api_docs/kbn_securitysolution_list_utils.mdx index 9a8afda4b7b7dd..22657a04b1bb90 100644 --- a/api_docs/kbn_securitysolution_list_utils.mdx +++ b/api_docs/kbn_securitysolution_list_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-utils title: "@kbn/securitysolution-list-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-utils plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-utils'] --- import kbnSecuritysolutionListUtilsObj from './kbn_securitysolution_list_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_rules.mdx b/api_docs/kbn_securitysolution_rules.mdx index bb843ea8ac0bcf..19a2c081a5bd76 100644 --- a/api_docs/kbn_securitysolution_rules.mdx +++ b/api_docs/kbn_securitysolution_rules.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-rules title: "@kbn/securitysolution-rules" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-rules plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-rules'] --- import kbnSecuritysolutionRulesObj from './kbn_securitysolution_rules.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_t_grid.mdx b/api_docs/kbn_securitysolution_t_grid.mdx index 1decc3b5849ea9..65f02eb6305e73 100644 --- a/api_docs/kbn_securitysolution_t_grid.mdx +++ b/api_docs/kbn_securitysolution_t_grid.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-t-grid title: "@kbn/securitysolution-t-grid" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-t-grid plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-t-grid'] --- import kbnSecuritysolutionTGridObj from './kbn_securitysolution_t_grid.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_utils.mdx b/api_docs/kbn_securitysolution_utils.mdx index 8b6696e13af386..f84326704b432b 100644 --- a/api_docs/kbn_securitysolution_utils.mdx +++ b/api_docs/kbn_securitysolution_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-utils title: "@kbn/securitysolution-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-utils plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-utils'] --- import kbnSecuritysolutionUtilsObj from './kbn_securitysolution_utils.devdocs.json'; diff --git a/api_docs/kbn_server_http_tools.mdx b/api_docs/kbn_server_http_tools.mdx index 7f521d04d76d9e..2553be04e72c4f 100644 --- a/api_docs/kbn_server_http_tools.mdx +++ b/api_docs/kbn_server_http_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-server-http-tools title: "@kbn/server-http-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/server-http-tools plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-http-tools'] --- import kbnServerHttpToolsObj from './kbn_server_http_tools.devdocs.json'; diff --git a/api_docs/kbn_server_route_repository.mdx b/api_docs/kbn_server_route_repository.mdx index 8ee1166df80bec..e1deb3f5d47f77 100644 --- a/api_docs/kbn_server_route_repository.mdx +++ b/api_docs/kbn_server_route_repository.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-server-route-repository title: "@kbn/server-route-repository" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/server-route-repository plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-route-repository'] --- import kbnServerRouteRepositoryObj from './kbn_server_route_repository.devdocs.json'; diff --git a/api_docs/kbn_shared_svg.mdx b/api_docs/kbn_shared_svg.mdx index 04dbdc8391d269..e28e8dfe7c35ae 100644 --- a/api_docs/kbn_shared_svg.mdx +++ b/api_docs/kbn_shared_svg.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-svg title: "@kbn/shared-svg" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-svg plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-svg'] --- import kbnSharedSvgObj from './kbn_shared_svg.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx b/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx index b5c2b30967bb44..57ee3c5eaeeac4 100644 --- a/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx +++ b/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-exit-full-screen-mocks title: "@kbn/shared-ux-button-exit-full-screen-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-exit-full-screen-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-exit-full-screen-mocks'] --- import kbnSharedUxButtonExitFullScreenMocksObj from './kbn_shared_ux_button_exit_full_screen_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_toolbar.mdx b/api_docs/kbn_shared_ux_button_toolbar.mdx index ac94fb48964515..823e9843677a0e 100644 --- a/api_docs/kbn_shared_ux_button_toolbar.mdx +++ b/api_docs/kbn_shared_ux_button_toolbar.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-toolbar title: "@kbn/shared-ux-button-toolbar" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-toolbar plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-toolbar'] --- import kbnSharedUxButtonToolbarObj from './kbn_shared_ux_button_toolbar.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_card_no_data.mdx b/api_docs/kbn_shared_ux_card_no_data.mdx index 110a972ba8eb2d..27455c0dcff207 100644 --- a/api_docs/kbn_shared_ux_card_no_data.mdx +++ b/api_docs/kbn_shared_ux_card_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-card-no-data title: "@kbn/shared-ux-card-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-card-no-data plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-card-no-data'] --- import kbnSharedUxCardNoDataObj from './kbn_shared_ux_card_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_card_no_data_mocks.mdx b/api_docs/kbn_shared_ux_card_no_data_mocks.mdx index 308f00a75d82ee..30e9422c7d0dcc 100644 --- a/api_docs/kbn_shared_ux_card_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_card_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-card-no-data-mocks title: "@kbn/shared-ux-card-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-card-no-data-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-card-no-data-mocks'] --- import kbnSharedUxCardNoDataMocksObj from './kbn_shared_ux_card_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx b/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx index 7456f342410420..d382db6b061811 100644 --- a/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx +++ b/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-link-redirect-app-mocks title: "@kbn/shared-ux-link-redirect-app-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-link-redirect-app-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-link-redirect-app-mocks'] --- import kbnSharedUxLinkRedirectAppMocksObj from './kbn_shared_ux_link_redirect_app_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_analytics_no_data.mdx b/api_docs/kbn_shared_ux_page_analytics_no_data.mdx index b7ae5b0fce0f94..f719f64919ffe1 100644 --- a/api_docs/kbn_shared_ux_page_analytics_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_analytics_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-analytics-no-data title: "@kbn/shared-ux-page-analytics-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-analytics-no-data plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-analytics-no-data'] --- import kbnSharedUxPageAnalyticsNoDataObj from './kbn_shared_ux_page_analytics_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx index 326b017b7d1184..6c98183d2a7ff0 100644 --- a/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-analytics-no-data-mocks title: "@kbn/shared-ux-page-analytics-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-analytics-no-data-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-analytics-no-data-mocks'] --- import kbnSharedUxPageAnalyticsNoDataMocksObj from './kbn_shared_ux_page_analytics_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_no_data.mdx b/api_docs/kbn_shared_ux_page_kibana_no_data.mdx index 9b1be63162af52..e96fd6b65b797d 100644 --- a/api_docs/kbn_shared_ux_page_kibana_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-no-data title: "@kbn/shared-ux-page-kibana-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-no-data plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-no-data'] --- import kbnSharedUxPageKibanaNoDataObj from './kbn_shared_ux_page_kibana_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx index fa6513e6cb2ca5..f082939bf23db8 100644 --- a/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-no-data-mocks title: "@kbn/shared-ux-page-kibana-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-no-data-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-no-data-mocks'] --- import kbnSharedUxPageKibanaNoDataMocksObj from './kbn_shared_ux_page_kibana_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_template.mdx b/api_docs/kbn_shared_ux_page_kibana_template.mdx index b285bd11d9a23b..56d513e6b23953 100644 --- a/api_docs/kbn_shared_ux_page_kibana_template.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_template.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-template title: "@kbn/shared-ux-page-kibana-template" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-template plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-template'] --- import kbnSharedUxPageKibanaTemplateObj from './kbn_shared_ux_page_kibana_template.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx b/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx index 6e3c33994da95e..f2aa470f834cc5 100644 --- a/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-template-mocks title: "@kbn/shared-ux-page-kibana-template-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-template-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-template-mocks'] --- import kbnSharedUxPageKibanaTemplateMocksObj from './kbn_shared_ux_page_kibana_template_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data.mdx b/api_docs/kbn_shared_ux_page_no_data.mdx index 9e88289417fd56..003b096cfd0f91 100644 --- a/api_docs/kbn_shared_ux_page_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data title: "@kbn/shared-ux-page-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data'] --- import kbnSharedUxPageNoDataObj from './kbn_shared_ux_page_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_config.mdx b/api_docs/kbn_shared_ux_page_no_data_config.mdx index 5f3e0e337b804a..8b61bc3b8fb032 100644 --- a/api_docs/kbn_shared_ux_page_no_data_config.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-config title: "@kbn/shared-ux-page-no-data-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-config plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-config'] --- import kbnSharedUxPageNoDataConfigObj from './kbn_shared_ux_page_no_data_config.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx b/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx index eb80ec1a245864..9b0e41366e4922 100644 --- a/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-config-mocks title: "@kbn/shared-ux-page-no-data-config-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-config-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-config-mocks'] --- import kbnSharedUxPageNoDataConfigMocksObj from './kbn_shared_ux_page_no_data_config_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_no_data_mocks.mdx index 642f5553769a61..673f7aa80d4184 100644 --- a/api_docs/kbn_shared_ux_page_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-mocks title: "@kbn/shared-ux-page-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-mocks'] --- import kbnSharedUxPageNoDataMocksObj from './kbn_shared_ux_page_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_solution_nav.mdx b/api_docs/kbn_shared_ux_page_solution_nav.mdx index b9374f8d8a976d..fca609edd1eec1 100644 --- a/api_docs/kbn_shared_ux_page_solution_nav.mdx +++ b/api_docs/kbn_shared_ux_page_solution_nav.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-solution-nav title: "@kbn/shared-ux-page-solution-nav" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-solution-nav plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-solution-nav'] --- import kbnSharedUxPageSolutionNavObj from './kbn_shared_ux_page_solution_nav.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_prompt_no_data_views.mdx b/api_docs/kbn_shared_ux_prompt_no_data_views.mdx index 59f4055671f045..d55f975104ffac 100644 --- a/api_docs/kbn_shared_ux_prompt_no_data_views.mdx +++ b/api_docs/kbn_shared_ux_prompt_no_data_views.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-no-data-views title: "@kbn/shared-ux-prompt-no-data-views" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-no-data-views plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-no-data-views'] --- import kbnSharedUxPromptNoDataViewsObj from './kbn_shared_ux_prompt_no_data_views.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx b/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx index 37e90a8eb138ca..370bb3fb7b081a 100644 --- a/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx +++ b/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-no-data-views-mocks title: "@kbn/shared-ux-prompt-no-data-views-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-no-data-views-mocks plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-no-data-views-mocks'] --- import kbnSharedUxPromptNoDataViewsMocksObj from './kbn_shared_ux_prompt_no_data_views_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_storybook_config.mdx b/api_docs/kbn_shared_ux_storybook_config.mdx index 61e123a44519c6..9200b11a09b215 100644 --- a/api_docs/kbn_shared_ux_storybook_config.mdx +++ b/api_docs/kbn_shared_ux_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-storybook-config title: "@kbn/shared-ux-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-storybook-config plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-storybook-config'] --- import kbnSharedUxStorybookConfigObj from './kbn_shared_ux_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_storybook_mock.mdx b/api_docs/kbn_shared_ux_storybook_mock.mdx index bf41c879e0c88e..d281f952bbbdfd 100644 --- a/api_docs/kbn_shared_ux_storybook_mock.mdx +++ b/api_docs/kbn_shared_ux_storybook_mock.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-storybook-mock title: "@kbn/shared-ux-storybook-mock" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-storybook-mock plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-storybook-mock'] --- import kbnSharedUxStorybookMockObj from './kbn_shared_ux_storybook_mock.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_utility.mdx b/api_docs/kbn_shared_ux_utility.mdx index a7d109aeaa0276..ce6cfca9bcf5c8 100644 --- a/api_docs/kbn_shared_ux_utility.mdx +++ b/api_docs/kbn_shared_ux_utility.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-utility title: "@kbn/shared-ux-utility" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-utility plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-utility'] --- import kbnSharedUxUtilityObj from './kbn_shared_ux_utility.devdocs.json'; diff --git a/api_docs/kbn_some_dev_log.mdx b/api_docs/kbn_some_dev_log.mdx index bcafbf060e852f..ef9f4272e5ae16 100644 --- a/api_docs/kbn_some_dev_log.mdx +++ b/api_docs/kbn_some_dev_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-some-dev-log title: "@kbn/some-dev-log" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/some-dev-log plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/some-dev-log'] --- import kbnSomeDevLogObj from './kbn_some_dev_log.devdocs.json'; diff --git a/api_docs/kbn_sort_package_json.mdx b/api_docs/kbn_sort_package_json.mdx index 711d3242b36c27..5e5cd15a358740 100644 --- a/api_docs/kbn_sort_package_json.mdx +++ b/api_docs/kbn_sort_package_json.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-sort-package-json title: "@kbn/sort-package-json" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/sort-package-json plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/sort-package-json'] --- import kbnSortPackageJsonObj from './kbn_sort_package_json.devdocs.json'; diff --git a/api_docs/kbn_std.mdx b/api_docs/kbn_std.mdx index f235b690509b6e..f09537bfe88aef 100644 --- a/api_docs/kbn_std.mdx +++ b/api_docs/kbn_std.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-std title: "@kbn/std" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/std plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/std'] --- import kbnStdObj from './kbn_std.devdocs.json'; diff --git a/api_docs/kbn_stdio_dev_helpers.mdx b/api_docs/kbn_stdio_dev_helpers.mdx index 5342e38297ac1b..9bd71879017ce6 100644 --- a/api_docs/kbn_stdio_dev_helpers.mdx +++ b/api_docs/kbn_stdio_dev_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-stdio-dev-helpers title: "@kbn/stdio-dev-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/stdio-dev-helpers plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/stdio-dev-helpers'] --- import kbnStdioDevHelpersObj from './kbn_stdio_dev_helpers.devdocs.json'; diff --git a/api_docs/kbn_storybook.mdx b/api_docs/kbn_storybook.mdx index cc0aa729278dc3..9a002696753d01 100644 --- a/api_docs/kbn_storybook.mdx +++ b/api_docs/kbn_storybook.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-storybook title: "@kbn/storybook" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/storybook plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/storybook'] --- import kbnStorybookObj from './kbn_storybook.devdocs.json'; diff --git a/api_docs/kbn_telemetry_tools.mdx b/api_docs/kbn_telemetry_tools.mdx index 3ac584012e8633..5b0eba5853c138 100644 --- a/api_docs/kbn_telemetry_tools.mdx +++ b/api_docs/kbn_telemetry_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-telemetry-tools title: "@kbn/telemetry-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/telemetry-tools plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/telemetry-tools'] --- import kbnTelemetryToolsObj from './kbn_telemetry_tools.devdocs.json'; diff --git a/api_docs/kbn_test.mdx b/api_docs/kbn_test.mdx index 0c35076ee177d1..2b1cfb4d5c2fe0 100644 --- a/api_docs/kbn_test.mdx +++ b/api_docs/kbn_test.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test title: "@kbn/test" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test'] --- import kbnTestObj from './kbn_test.devdocs.json'; diff --git a/api_docs/kbn_test_jest_helpers.mdx b/api_docs/kbn_test_jest_helpers.mdx index f69d950a6020de..20c4a3eb4f9ba7 100644 --- a/api_docs/kbn_test_jest_helpers.mdx +++ b/api_docs/kbn_test_jest_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test-jest-helpers title: "@kbn/test-jest-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test-jest-helpers plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-jest-helpers'] --- import kbnTestJestHelpersObj from './kbn_test_jest_helpers.devdocs.json'; diff --git a/api_docs/kbn_tooling_log.mdx b/api_docs/kbn_tooling_log.mdx index 34eb25abce6269..fb392e818e687e 100644 --- a/api_docs/kbn_tooling_log.mdx +++ b/api_docs/kbn_tooling_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-tooling-log title: "@kbn/tooling-log" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/tooling-log plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/tooling-log'] --- import kbnToolingLogObj from './kbn_tooling_log.devdocs.json'; diff --git a/api_docs/kbn_type_summarizer.mdx b/api_docs/kbn_type_summarizer.mdx index 36d4e190e9df96..c06226b8eba969 100644 --- a/api_docs/kbn_type_summarizer.mdx +++ b/api_docs/kbn_type_summarizer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-type-summarizer title: "@kbn/type-summarizer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/type-summarizer plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/type-summarizer'] --- import kbnTypeSummarizerObj from './kbn_type_summarizer.devdocs.json'; diff --git a/api_docs/kbn_type_summarizer_core.mdx b/api_docs/kbn_type_summarizer_core.mdx index 8322a666bd9e7d..b81adb3a56d1d1 100644 --- a/api_docs/kbn_type_summarizer_core.mdx +++ b/api_docs/kbn_type_summarizer_core.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-type-summarizer-core title: "@kbn/type-summarizer-core" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/type-summarizer-core plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/type-summarizer-core'] --- import kbnTypeSummarizerCoreObj from './kbn_type_summarizer_core.devdocs.json'; diff --git a/api_docs/kbn_typed_react_router_config.mdx b/api_docs/kbn_typed_react_router_config.mdx index 7a592007512c20..e75d872f2484db 100644 --- a/api_docs/kbn_typed_react_router_config.mdx +++ b/api_docs/kbn_typed_react_router_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-typed-react-router-config title: "@kbn/typed-react-router-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/typed-react-router-config plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/typed-react-router-config'] --- import kbnTypedReactRouterConfigObj from './kbn_typed_react_router_config.devdocs.json'; diff --git a/api_docs/kbn_ui_theme.mdx b/api_docs/kbn_ui_theme.mdx index cf0cc5cb05b938..b70ee2231fefb1 100644 --- a/api_docs/kbn_ui_theme.mdx +++ b/api_docs/kbn_ui_theme.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-theme title: "@kbn/ui-theme" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-theme plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-theme'] --- import kbnUiThemeObj from './kbn_ui_theme.devdocs.json'; diff --git a/api_docs/kbn_user_profile_components.mdx b/api_docs/kbn_user_profile_components.mdx index 10bf9f95e7101d..b7ddf660ca0df5 100644 --- a/api_docs/kbn_user_profile_components.mdx +++ b/api_docs/kbn_user_profile_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-user-profile-components title: "@kbn/user-profile-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/user-profile-components plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/user-profile-components'] --- import kbnUserProfileComponentsObj from './kbn_user_profile_components.devdocs.json'; diff --git a/api_docs/kbn_utility_types.mdx b/api_docs/kbn_utility_types.mdx index 683fa55fa6a85b..92cd97760ca7c9 100644 --- a/api_docs/kbn_utility_types.mdx +++ b/api_docs/kbn_utility_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utility-types title: "@kbn/utility-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utility-types plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utility-types'] --- import kbnUtilityTypesObj from './kbn_utility_types.devdocs.json'; diff --git a/api_docs/kbn_utility_types_jest.mdx b/api_docs/kbn_utility_types_jest.mdx index d5a46f16e6952a..af84fa702b0759 100644 --- a/api_docs/kbn_utility_types_jest.mdx +++ b/api_docs/kbn_utility_types_jest.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utility-types-jest title: "@kbn/utility-types-jest" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utility-types-jest plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utility-types-jest'] --- import kbnUtilityTypesJestObj from './kbn_utility_types_jest.devdocs.json'; diff --git a/api_docs/kbn_utils.mdx b/api_docs/kbn_utils.mdx index be96bc7150be99..c6f2cc8482954a 100644 --- a/api_docs/kbn_utils.mdx +++ b/api_docs/kbn_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utils title: "@kbn/utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utils plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utils'] --- import kbnUtilsObj from './kbn_utils.devdocs.json'; diff --git a/api_docs/kbn_yarn_lock_validator.mdx b/api_docs/kbn_yarn_lock_validator.mdx index cf64f2eb0c9773..789133a70ac7ec 100644 --- a/api_docs/kbn_yarn_lock_validator.mdx +++ b/api_docs/kbn_yarn_lock_validator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-yarn-lock-validator title: "@kbn/yarn-lock-validator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/yarn-lock-validator plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/yarn-lock-validator'] --- import kbnYarnLockValidatorObj from './kbn_yarn_lock_validator.devdocs.json'; diff --git a/api_docs/kibana_overview.mdx b/api_docs/kibana_overview.mdx index 9a6d98afc51941..4ea296d9ab1e1a 100644 --- a/api_docs/kibana_overview.mdx +++ b/api_docs/kibana_overview.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaOverview title: "kibanaOverview" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaOverview plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaOverview'] --- import kibanaOverviewObj from './kibana_overview.devdocs.json'; diff --git a/api_docs/kibana_react.mdx b/api_docs/kibana_react.mdx index aa062aa0b26d68..d69d9e8545c969 100644 --- a/api_docs/kibana_react.mdx +++ b/api_docs/kibana_react.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaReact title: "kibanaReact" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaReact plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaReact'] --- import kibanaReactObj from './kibana_react.devdocs.json'; diff --git a/api_docs/kibana_utils.mdx b/api_docs/kibana_utils.mdx index 737bd6f780b0e8..169dcb7ee1f23b 100644 --- a/api_docs/kibana_utils.mdx +++ b/api_docs/kibana_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaUtils title: "kibanaUtils" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaUtils plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaUtils'] --- import kibanaUtilsObj from './kibana_utils.devdocs.json'; diff --git a/api_docs/kubernetes_security.mdx b/api_docs/kubernetes_security.mdx index 0adc33bfc6e810..7f3978dab8e032 100644 --- a/api_docs/kubernetes_security.mdx +++ b/api_docs/kubernetes_security.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kubernetesSecurity title: "kubernetesSecurity" image: https://source.unsplash.com/400x175/?github description: API docs for the kubernetesSecurity plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kubernetesSecurity'] --- import kubernetesSecurityObj from './kubernetes_security.devdocs.json'; diff --git a/api_docs/lens.devdocs.json b/api_docs/lens.devdocs.json index 10aed71c09d2e2..76f715bdb21c98 100644 --- a/api_docs/lens.devdocs.json +++ b/api_docs/lens.devdocs.json @@ -2715,7 +2715,7 @@ "section": "def-public.Visualization", "text": "Visualization" }, - " | (() => Promise<", + " | (() => Promise<", { "pluginId": "lens", "scope": "public", @@ -2723,7 +2723,7 @@ "section": "def-public.Visualization", "text": "Visualization" }, - ">)) => void" + ">)) => void" ], "path": "x-pack/plugins/lens/public/plugin.ts", "deprecated": false, @@ -2744,7 +2744,7 @@ "section": "def-public.Visualization", "text": "Visualization" }, - " | (() => Promise<", + " | (() => Promise<", { "pluginId": "lens", "scope": "public", @@ -2752,7 +2752,7 @@ "section": "def-public.Visualization", "text": "Visualization" }, - ">)" + ">)" ], "path": "x-pack/plugins/lens/public/plugin.ts", "deprecated": false, @@ -3125,6 +3125,20 @@ "deprecated": false, "trackAdoption": false, "children": [ + { + "parentPluginId": "lens", + "id": "def-public.OperationMetadata.interval", + "type": "string", + "tags": [], + "label": "interval", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "x-pack/plugins/lens/public/types.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "lens", "id": "def-public.OperationMetadata.dataType", @@ -4122,7 +4136,7 @@ "section": "def-public.Visualization", "text": "Visualization" }, - "" + "" ], "path": "x-pack/plugins/lens/public/types.ts", "deprecated": false, @@ -4148,7 +4162,7 @@ "tags": [], "label": "initialize", "description": [ - "\nInitialize is allowed to modify the state stored in memory. The initialize function\nis called with a previous state in two cases:\n- Loadingn from a saved visualization\n- When using suggestions, the suggested state is passed in" + "\nInitialize is allowed to modify the state stored in memory. The initialize function\nis called with a previous state in two cases:\n- Loading from a saved visualization\n- When using suggestions, the suggested state is passed in" ], "signature": [ "(addNewLayer: () => string, state?: T | undefined, mainPalette?: ", @@ -4208,6 +4222,40 @@ ], "returnComment": [] }, + { + "parentPluginId": "lens", + "id": "def-public.Visualization.getUsedDataViews", + "type": "Function", + "tags": [], + "label": "getUsedDataViews", + "description": [ + "\nRetrieve the used DataViews in the visualization" + ], + "signature": [ + "((state?: T | undefined) => string[]) | undefined" + ], + "path": "x-pack/plugins/lens/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "lens", + "id": "def-public.Visualization.getUsedDataViews.$1", + "type": "Uncategorized", + "tags": [], + "label": "state", + "description": [], + "signature": [ + "T | undefined" + ], + "path": "x-pack/plugins/lens/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, { "parentPluginId": "lens", "id": "def-public.Visualization.getMainPalette", @@ -4394,6 +4442,94 @@ ], "returnComment": [] }, + { + "parentPluginId": "lens", + "id": "def-public.Visualization.getPersistableState", + "type": "Function", + "tags": [], + "label": "getPersistableState", + "description": [ + "Visualizations can have references as well" + ], + "signature": [ + "((state: T) => { state: P; savedObjectReferences: ", + "SavedObjectReference", + "[]; }) | undefined" + ], + "path": "x-pack/plugins/lens/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "lens", + "id": "def-public.Visualization.getPersistableState.$1", + "type": "Uncategorized", + "tags": [], + "label": "state", + "description": [], + "signature": [ + "T" + ], + "path": "x-pack/plugins/lens/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "lens", + "id": "def-public.Visualization.fromPersistableState", + "type": "Function", + "tags": [], + "label": "fromPersistableState", + "description": [ + "Hydrate from persistable state and references to final state" + ], + "signature": [ + "((state: P, references?: ", + "SavedObjectReference", + "[] | undefined) => T) | undefined" + ], + "path": "x-pack/plugins/lens/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "lens", + "id": "def-public.Visualization.fromPersistableState.$1", + "type": "Uncategorized", + "tags": [], + "label": "state", + "description": [], + "signature": [ + "P" + ], + "path": "x-pack/plugins/lens/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "lens", + "id": "def-public.Visualization.fromPersistableState.$2", + "type": "Array", + "tags": [], + "label": "references", + "description": [], + "signature": [ + "SavedObjectReference", + "[] | undefined" + ], + "path": "x-pack/plugins/lens/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, { "parentPluginId": "lens", "id": "def-public.Visualization.getLayerIds", @@ -4438,7 +4574,7 @@ "Reset button on each layer triggers this" ], "signature": [ - "(state: T, layerId: string) => T" + "(state: T, layerId: string, indexPatternId: string) => T" ], "path": "x-pack/plugins/lens/public/types.ts", "deprecated": false, @@ -4473,6 +4609,21 @@ "deprecated": false, "trackAdoption": false, "isRequired": true + }, + { + "parentPluginId": "lens", + "id": "def-public.Visualization.clearLayer.$3", + "type": "string", + "tags": [], + "label": "indexPatternId", + "description": [], + "signature": [ + "string" + ], + "path": "x-pack/plugins/lens/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true } ], "returnComment": [] @@ -4544,7 +4695,7 @@ "section": "def-common.LayerType", "text": "LayerType" }, - ", indexPatternId?: string | undefined) => T) | undefined" + ", indexPatternId: string) => T) | undefined" ], "path": "x-pack/plugins/lens/public/types.ts", "deprecated": false, @@ -4609,12 +4760,12 @@ "label": "indexPatternId", "description": [], "signature": [ - "string | undefined" + "string" ], "path": "x-pack/plugins/lens/public/types.ts", "deprecated": false, "trackAdoption": false, - "isRequired": false + "isRequired": true } ], "returnComment": [] @@ -5750,15 +5901,9 @@ "\nThe frame will call this function on all visualizations at few stages (pre-build/build error) in order\nto provide more context to the error and show it to the user" ], "signature": [ - "(state: T, datasourceLayers?: Partial> | undefined) => { shortMessage: string; longMessage: React.ReactNode; }[] | undefined" + "(state: T, frame?: Pick<", + "FramePublicAPI", + ", \"dataViews\" | \"datasourceLayers\"> | undefined) => { shortMessage: string; longMessage: React.ReactNode; }[] | undefined" ], "path": "x-pack/plugins/lens/public/types.ts", "deprecated": false, @@ -5784,18 +5929,111 @@ "id": "def-public.Visualization.getErrorMessages.$2", "type": "Object", "tags": [], - "label": "datasourceLayers", + "label": "frame", "description": [], "signature": [ - "Partial> | undefined" + "Pick<", + "FramePublicAPI", + ", \"dataViews\" | \"datasourceLayers\"> | undefined" + ], + "path": "x-pack/plugins/lens/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "lens", + "id": "def-public.Visualization.validateColumn", + "type": "Function", + "tags": [], + "label": "validateColumn", + "description": [], + "signature": [ + "((state: T, frame: Pick<", + "FramePublicAPI", + ", \"dataViews\">, layerId: string, columnId: string, group?: ", + "VisualizationDimensionGroupConfig", + " | undefined) => { invalid: boolean; invalidMessage?: string | undefined; }) | undefined" + ], + "path": "x-pack/plugins/lens/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "lens", + "id": "def-public.Visualization.validateColumn.$1", + "type": "Uncategorized", + "tags": [], + "label": "state", + "description": [], + "signature": [ + "T" + ], + "path": "x-pack/plugins/lens/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "lens", + "id": "def-public.Visualization.validateColumn.$2", + "type": "Object", + "tags": [], + "label": "frame", + "description": [], + "signature": [ + "Pick<", + "FramePublicAPI", + ", \"dataViews\">" + ], + "path": "x-pack/plugins/lens/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "lens", + "id": "def-public.Visualization.validateColumn.$3", + "type": "string", + "tags": [], + "label": "layerId", + "description": [], + "signature": [ + "string" + ], + "path": "x-pack/plugins/lens/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "lens", + "id": "def-public.Visualization.validateColumn.$4", + "type": "string", + "tags": [], + "label": "columnId", + "description": [], + "signature": [ + "string" + ], + "path": "x-pack/plugins/lens/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "lens", + "id": "def-public.Visualization.validateColumn.$5", + "type": "CompoundType", + "tags": [], + "label": "group", + "description": [], + "signature": [ + "VisualizationDimensionGroupConfig", + " | undefined" ], "path": "x-pack/plugins/lens/public/types.ts", "deprecated": false, @@ -6252,6 +6490,31 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "lens", + "id": "def-public.XYAnnotationLayerConfig.hide", + "type": "CompoundType", + "tags": [], + "label": "hide", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "x-pack/plugins/lens/public/visualizations/xy/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "lens", + "id": "def-public.XYAnnotationLayerConfig.indexPatternId", + "type": "string", + "tags": [], + "label": "indexPatternId", + "description": [], + "path": "x-pack/plugins/lens/public/visualizations/xy/types.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "lens", "id": "def-public.XYAnnotationLayerConfig.simpleView", @@ -6382,21 +6645,6 @@ "deprecated": false, "trackAdoption": false }, - { - "parentPluginId": "lens", - "id": "def-public.XYArgs.annotationLayers", - "type": "Array", - "tags": [], - "label": "annotationLayers", - "description": [], - "signature": [ - "AnnotationLayerConfigResult", - "[]" - ], - "path": "src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts", - "deprecated": false, - "trackAdoption": false - }, { "parentPluginId": "lens", "id": "def-public.XYArgs.fittingFunction", @@ -8675,30 +8923,7 @@ "path": "x-pack/plugins/lens/server/plugin.tsx", "deprecated": false, "trackAdoption": false, - "children": [ - { - "parentPluginId": "lens", - "id": "def-server.LensServerPlugin.Unnamed.$1", - "type": "Object", - "tags": [], - "label": "initializerContext", - "description": [], - "signature": [ - { - "pluginId": "core", - "scope": "server", - "docId": "kibCorePluginApi", - "section": "def-server.PluginInitializerContext", - "text": "PluginInitializerContext" - }, - "" - ], - "path": "x-pack/plugins/lens/server/plugin.tsx", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], + "children": [], "returnComment": [] }, { @@ -9436,6 +9661,62 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "lens", + "id": "def-server.XYVisState850", + "type": "Interface", + "tags": [], + "label": "XYVisState850", + "description": [], + "path": "x-pack/plugins/lens/server/migrations/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "lens", + "id": "def-server.XYVisState850.layers", + "type": "Array", + "tags": [], + "label": "layers", + "description": [], + "signature": [ + "({ layerId: string; layerType: \"data\" | \"referenceLine\"; } | { layerId: string; layerType: \"annotations\"; annotations: { id: string; type: \"query\" | \"manual\"; }[]; })[]" + ], + "path": "x-pack/plugins/lens/server/migrations/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "lens", + "id": "def-server.XYVisStatePre850", + "type": "Interface", + "tags": [], + "label": "XYVisStatePre850", + "description": [], + "path": "x-pack/plugins/lens/server/migrations/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "lens", + "id": "def-server.XYVisStatePre850.layers", + "type": "Array", + "tags": [], + "label": "layers", + "description": [], + "signature": [ + "({ layerId: string; layerType: \"data\" | \"referenceLine\"; } | { layerId: string; layerType: \"annotations\"; annotations: { id: string; }[]; })[]" + ], + "path": "x-pack/plugins/lens/server/migrations/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "lens", "id": "def-server.XYVisualizationState830", @@ -9937,6 +10218,27 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "lens", + "id": "def-server.VisState850", + "type": "Type", + "tags": [], + "label": "VisState850", + "description": [], + "signature": [ + { + "pluginId": "lens", + "scope": "server", + "docId": "kibLensPluginApi", + "section": "def-server.XYVisState850", + "text": "XYVisState850" + } + ], + "path": "x-pack/plugins/lens/server/migrations/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "lens", "id": "def-server.VisStatePost715", diff --git a/api_docs/lens.mdx b/api_docs/lens.mdx index e3bf3ec6bd2ea7..a22c71323b68cd 100644 --- a/api_docs/lens.mdx +++ b/api_docs/lens.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/lens title: "lens" image: https://source.unsplash.com/400x175/?github description: API docs for the lens plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lens'] --- import lensObj from './lens.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 619 | 0 | 533 | 41 | +| 639 | 0 | 550 | 41 | ## Client diff --git a/api_docs/license_api_guard.mdx b/api_docs/license_api_guard.mdx index 9cbe965feabc54..571dc8691bd0a7 100644 --- a/api_docs/license_api_guard.mdx +++ b/api_docs/license_api_guard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licenseApiGuard title: "licenseApiGuard" image: https://source.unsplash.com/400x175/?github description: API docs for the licenseApiGuard plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licenseApiGuard'] --- import licenseApiGuardObj from './license_api_guard.devdocs.json'; diff --git a/api_docs/license_management.mdx b/api_docs/license_management.mdx index 0f41b6ae3352d8..201e1c21dffbc6 100644 --- a/api_docs/license_management.mdx +++ b/api_docs/license_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licenseManagement title: "licenseManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the licenseManagement plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licenseManagement'] --- import licenseManagementObj from './license_management.devdocs.json'; diff --git a/api_docs/licensing.mdx b/api_docs/licensing.mdx index 49646741c77fcb..d00e7742b2ed4a 100644 --- a/api_docs/licensing.mdx +++ b/api_docs/licensing.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licensing title: "licensing" image: https://source.unsplash.com/400x175/?github description: API docs for the licensing plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licensing'] --- import licensingObj from './licensing.devdocs.json'; diff --git a/api_docs/lists.devdocs.json b/api_docs/lists.devdocs.json index 2eb1993fbe171e..fe03f21a111554 100644 --- a/api_docs/lists.devdocs.json +++ b/api_docs/lists.devdocs.json @@ -1129,7 +1129,7 @@ "\nFinds an exception list item given a set of criteria." ], "signature": [ - "({ listId, filter, perPage, pit, page, searchAfter, sortField, sortOrder, namespaceType, }: ", + "({ listId, filter, perPage, pit, page, search, searchAfter, sortField, sortOrder, namespaceType, }: ", "FindExceptionListItemOptions", ") => Promise<({ data: { _version: string | undefined; comments: ({ comment: string; created_at: string; created_by: string; id: string; } & { updated_at?: string | undefined; updated_by?: string | undefined; })[]; created_at: string; created_by: string; description: string; entries: ({ field: string; operator: \"excluded\" | \"included\"; type: \"match\"; value: string; } | { field: string; operator: \"excluded\" | \"included\"; type: \"match_any\"; value: string[]; } | { field: string; list: { id: string; type: \"boolean\" | \"date\" | \"keyword\" | \"ip\" | \"text\" | \"geo_point\" | \"geo_shape\" | \"date_nanos\" | \"long\" | \"double\" | \"date_range\" | \"ip_range\" | \"shape\" | \"short\" | \"binary\" | \"float\" | \"half_float\" | \"integer\" | \"byte\" | \"long_range\" | \"integer_range\" | \"float_range\" | \"double_range\"; }; operator: \"excluded\" | \"included\"; type: \"list\"; } | { field: string; operator: \"excluded\" | \"included\"; type: \"exists\"; } | { entries: ({ field: string; operator: \"excluded\" | \"included\"; type: \"exists\"; } | { field: string; operator: \"excluded\" | \"included\"; type: \"match\"; value: string; } | { field: string; operator: \"excluded\" | \"included\"; type: \"match_any\"; value: string[]; })[]; field: string; type: \"nested\"; } | { field: string; operator: \"excluded\" | \"included\"; type: \"wildcard\"; value: string; })[]; id: string; item_id: string; list_id: string; meta: object | undefined; name: string; namespace_type: \"single\" | \"agnostic\"; os_types: (\"windows\" | \"linux\" | \"macos\")[]; tags: string[]; tie_breaker_id: string; type: \"simple\"; updated_at: string; updated_by: string; }[]; page: number; per_page: number; total: number; } & { pit?: string | undefined; }) | null>" ], @@ -1142,7 +1142,7 @@ "id": "def-server.ExceptionListClient.findExceptionListItem.$1", "type": "Object", "tags": [], - "label": "{\n listId,\n filter,\n perPage,\n pit,\n page,\n searchAfter,\n sortField,\n sortOrder,\n namespaceType,\n }", + "label": "{\n listId,\n filter,\n perPage,\n pit,\n page,\n search,\n searchAfter,\n sortField,\n sortOrder,\n namespaceType,\n }", "description": [], "signature": [ "FindExceptionListItemOptions" @@ -1167,7 +1167,7 @@ "\nFinds exception lists items given a set of criteria." ], "signature": [ - "({ listId, filter, perPage, pit, page, searchAfter, sortField, sortOrder, namespaceType, }: ", + "({ listId, filter, perPage, pit, page, search, searchAfter, sortField, sortOrder, namespaceType, }: ", "FindExceptionListsItemOptions", ") => Promise<({ data: { _version: string | undefined; comments: ({ comment: string; created_at: string; created_by: string; id: string; } & { updated_at?: string | undefined; updated_by?: string | undefined; })[]; created_at: string; created_by: string; description: string; entries: ({ field: string; operator: \"excluded\" | \"included\"; type: \"match\"; value: string; } | { field: string; operator: \"excluded\" | \"included\"; type: \"match_any\"; value: string[]; } | { field: string; list: { id: string; type: \"boolean\" | \"date\" | \"keyword\" | \"ip\" | \"text\" | \"geo_point\" | \"geo_shape\" | \"date_nanos\" | \"long\" | \"double\" | \"date_range\" | \"ip_range\" | \"shape\" | \"short\" | \"binary\" | \"float\" | \"half_float\" | \"integer\" | \"byte\" | \"long_range\" | \"integer_range\" | \"float_range\" | \"double_range\"; }; operator: \"excluded\" | \"included\"; type: \"list\"; } | { field: string; operator: \"excluded\" | \"included\"; type: \"exists\"; } | { entries: ({ field: string; operator: \"excluded\" | \"included\"; type: \"exists\"; } | { field: string; operator: \"excluded\" | \"included\"; type: \"match\"; value: string; } | { field: string; operator: \"excluded\" | \"included\"; type: \"match_any\"; value: string[]; })[]; field: string; type: \"nested\"; } | { field: string; operator: \"excluded\" | \"included\"; type: \"wildcard\"; value: string; })[]; id: string; item_id: string; list_id: string; meta: object | undefined; name: string; namespace_type: \"single\" | \"agnostic\"; os_types: (\"windows\" | \"linux\" | \"macos\")[]; tags: string[]; tie_breaker_id: string; type: \"simple\"; updated_at: string; updated_by: string; }[]; page: number; per_page: number; total: number; } & { pit?: string | undefined; }) | null>" ], @@ -1180,7 +1180,7 @@ "id": "def-server.ExceptionListClient.findExceptionListsItem.$1", "type": "Object", "tags": [], - "label": "{\n listId,\n filter,\n perPage,\n pit,\n page,\n searchAfter,\n sortField,\n sortOrder,\n namespaceType,\n }", + "label": "{\n listId,\n filter,\n perPage,\n pit,\n page,\n search,\n searchAfter,\n sortField,\n sortOrder,\n namespaceType,\n }", "description": [], "signature": [ "FindExceptionListsItemOptions" @@ -1281,7 +1281,7 @@ "\nThis is the same as \"findExceptionList\" except it applies specifically to the endpoint list and will\nauto-call the \"createEndpointList\" for you so that you have the best chance of the endpoint\nbeing there if it did not exist before. If the list did not exist before, then creating it here should give you\na good guarantee that you will get an empty record set rather than null. I keep the null as the return value in\nthe off chance that you still might somehow not get into a race condition where the endpoint list does\nnot exist because someone deleted it in-between the initial create and then the find." ], "signature": [ - "({ filter, perPage, page, pit, searchAfter, sortField, sortOrder, }: ", + "({ filter, perPage, page, pit, search, searchAfter, sortField, sortOrder, }: ", "FindEndpointListItemOptions", ") => Promise<({ data: { _version: string | undefined; comments: ({ comment: string; created_at: string; created_by: string; id: string; } & { updated_at?: string | undefined; updated_by?: string | undefined; })[]; created_at: string; created_by: string; description: string; entries: ({ field: string; operator: \"excluded\" | \"included\"; type: \"match\"; value: string; } | { field: string; operator: \"excluded\" | \"included\"; type: \"match_any\"; value: string[]; } | { field: string; list: { id: string; type: \"boolean\" | \"date\" | \"keyword\" | \"ip\" | \"text\" | \"geo_point\" | \"geo_shape\" | \"date_nanos\" | \"long\" | \"double\" | \"date_range\" | \"ip_range\" | \"shape\" | \"short\" | \"binary\" | \"float\" | \"half_float\" | \"integer\" | \"byte\" | \"long_range\" | \"integer_range\" | \"float_range\" | \"double_range\"; }; operator: \"excluded\" | \"included\"; type: \"list\"; } | { field: string; operator: \"excluded\" | \"included\"; type: \"exists\"; } | { entries: ({ field: string; operator: \"excluded\" | \"included\"; type: \"exists\"; } | { field: string; operator: \"excluded\" | \"included\"; type: \"match\"; value: string; } | { field: string; operator: \"excluded\" | \"included\"; type: \"match_any\"; value: string[]; })[]; field: string; type: \"nested\"; } | { field: string; operator: \"excluded\" | \"included\"; type: \"wildcard\"; value: string; })[]; id: string; item_id: string; list_id: string; meta: object | undefined; name: string; namespace_type: \"single\" | \"agnostic\"; os_types: (\"windows\" | \"linux\" | \"macos\")[]; tags: string[]; tie_breaker_id: string; type: \"simple\"; updated_at: string; updated_by: string; }[]; page: number; per_page: number; total: number; } & { pit?: string | undefined; }) | null>" ], @@ -1294,7 +1294,7 @@ "id": "def-server.ExceptionListClient.findEndpointListItem.$1", "type": "Object", "tags": [], - "label": "{\n filter,\n perPage,\n page,\n pit,\n searchAfter,\n sortField,\n sortOrder,\n }", + "label": "{\n filter,\n perPage,\n page,\n pit,\n search,\n searchAfter,\n sortField,\n sortOrder,\n }", "description": [], "signature": [ "FindEndpointListItemOptions" diff --git a/api_docs/lists.mdx b/api_docs/lists.mdx index 4898b58a53d7c2..751f7ca0cd136b 100644 --- a/api_docs/lists.mdx +++ b/api_docs/lists.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/lists title: "lists" image: https://source.unsplash.com/400x175/?github description: API docs for the lists plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lists'] --- import listsObj from './lists.devdocs.json'; diff --git a/api_docs/management.mdx b/api_docs/management.mdx index c80c65e2fcc23e..9a598bdde11fb4 100644 --- a/api_docs/management.mdx +++ b/api_docs/management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/management title: "management" image: https://source.unsplash.com/400x175/?github description: API docs for the management plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'management'] --- import managementObj from './management.devdocs.json'; diff --git a/api_docs/maps.mdx b/api_docs/maps.mdx index 3288a39e333ce0..fb06fd880fdb03 100644 --- a/api_docs/maps.mdx +++ b/api_docs/maps.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/maps title: "maps" image: https://source.unsplash.com/400x175/?github description: API docs for the maps plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'maps'] --- import mapsObj from './maps.devdocs.json'; diff --git a/api_docs/maps_ems.mdx b/api_docs/maps_ems.mdx index d77d00574c79ff..ff860e62ea1b92 100644 --- a/api_docs/maps_ems.mdx +++ b/api_docs/maps_ems.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/mapsEms title: "mapsEms" image: https://source.unsplash.com/400x175/?github description: API docs for the mapsEms plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'mapsEms'] --- import mapsEmsObj from './maps_ems.devdocs.json'; diff --git a/api_docs/ml.mdx b/api_docs/ml.mdx index a97b25d34c3b1d..ed642dcfa50a63 100644 --- a/api_docs/ml.mdx +++ b/api_docs/ml.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ml title: "ml" image: https://source.unsplash.com/400x175/?github description: API docs for the ml plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ml'] --- import mlObj from './ml.devdocs.json'; diff --git a/api_docs/monitoring.mdx b/api_docs/monitoring.mdx index 61c9858dabfd45..ddf5e670048441 100644 --- a/api_docs/monitoring.mdx +++ b/api_docs/monitoring.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/monitoring title: "monitoring" image: https://source.unsplash.com/400x175/?github description: API docs for the monitoring plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'monitoring'] --- import monitoringObj from './monitoring.devdocs.json'; diff --git a/api_docs/monitoring_collection.mdx b/api_docs/monitoring_collection.mdx index 1c108a0ab43d8f..6fb7aa53be7c72 100644 --- a/api_docs/monitoring_collection.mdx +++ b/api_docs/monitoring_collection.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/monitoringCollection title: "monitoringCollection" image: https://source.unsplash.com/400x175/?github description: API docs for the monitoringCollection plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'monitoringCollection'] --- import monitoringCollectionObj from './monitoring_collection.devdocs.json'; diff --git a/api_docs/navigation.mdx b/api_docs/navigation.mdx index d54a3cbd584866..e92a9aab1928c8 100644 --- a/api_docs/navigation.mdx +++ b/api_docs/navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/navigation title: "navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the navigation plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'navigation'] --- import navigationObj from './navigation.devdocs.json'; diff --git a/api_docs/newsfeed.mdx b/api_docs/newsfeed.mdx index 5bcbade38769b8..ef7c19dc1b7fea 100644 --- a/api_docs/newsfeed.mdx +++ b/api_docs/newsfeed.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/newsfeed title: "newsfeed" image: https://source.unsplash.com/400x175/?github description: API docs for the newsfeed plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'newsfeed'] --- import newsfeedObj from './newsfeed.devdocs.json'; diff --git a/api_docs/observability.mdx b/api_docs/observability.mdx index 346c966d5b6172..7a1e6c0e0601f9 100644 --- a/api_docs/observability.mdx +++ b/api_docs/observability.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observability title: "observability" image: https://source.unsplash.com/400x175/?github description: API docs for the observability plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observability'] --- import observabilityObj from './observability.devdocs.json'; diff --git a/api_docs/osquery.mdx b/api_docs/osquery.mdx index cca97c6fe10be7..8398670e49a38f 100644 --- a/api_docs/osquery.mdx +++ b/api_docs/osquery.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/osquery title: "osquery" image: https://source.unsplash.com/400x175/?github description: API docs for the osquery plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'osquery'] --- import osqueryObj from './osquery.devdocs.json'; diff --git a/api_docs/plugin_directory.mdx b/api_docs/plugin_directory.mdx index 6dfa0eb3a39c15..f6762a00b3cc2c 100644 --- a/api_docs/plugin_directory.mdx +++ b/api_docs/plugin_directory.mdx @@ -7,7 +7,7 @@ id: kibDevDocsPluginDirectory slug: /kibana-dev-docs/api-meta/plugin-api-directory title: Directory description: Directory of public APIs available through plugins or packages. -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -15,13 +15,13 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | Count | Plugins or Packages with a
public API | Number of teams | |--------------|----------|------------------------| -| 444 | 369 | 36 | +| 442 | 368 | 36 | ### Public API health stats | API Count | Any Count | Missing comments | Missing exports | |--------------|----------|-----------------|--------| -| 30582 | 180 | 20435 | 973 | +| 30641 | 180 | 20479 | 966 | ## Plugin Directory @@ -29,14 +29,14 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] |--------------|----------------|-----------|--------------|----------|---------------|--------| | | [Response Ops](https://github.com/orgs/elastic/teams/response-ops) | - | 272 | 0 | 267 | 19 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 23 | 0 | 19 | 1 | -| | [Machine Learning UI](https://github.com/orgs/elastic/teams/ml-ui) | AIOps plugin maintained by ML team. | 9 | 0 | 0 | 1 | +| | [Machine Learning UI](https://github.com/orgs/elastic/teams/ml-ui) | AIOps plugin maintained by ML team. | 7 | 0 | 0 | 1 | | | [Response Ops](https://github.com/orgs/elastic/teams/response-ops) | - | 368 | 0 | 359 | 21 | | | [APM UI](https://github.com/orgs/elastic/teams/apm-ui) | The user interface for Elastic APM | 39 | 0 | 39 | 54 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 9 | 0 | 9 | 0 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Considering using bfetch capabilities when fetching large amounts of data. This services supports batching HTTP requests and streaming responses back. | 80 | 1 | 71 | 2 | | | [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds Canvas application to Kibana | 9 | 0 | 8 | 3 | | | [ResponseOps](https://github.com/orgs/elastic/teams/response-ops) | The Case management system in Kibana | 84 | 0 | 68 | 29 | -| | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | - | 261 | 2 | 246 | 9 | +| | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | - | 264 | 2 | 249 | 9 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 29 | 0 | 24 | 0 | | | [Cloud Security Posture](https://github.com/orgs/elastic/teams/cloud-posture-security) | The cloud security posture plugin | 18 | 0 | 2 | 3 | | | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 13 | 0 | 13 | 1 | @@ -46,7 +46,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Fleet](https://github.com/orgs/elastic/teams/fleet) | Add custom data integrations so they can be displayed in the Fleet integrations app | 102 | 0 | 83 | 1 | | | [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds the Dashboard app to Kibana | 147 | 0 | 142 | 12 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | - | 52 | 0 | 51 | 0 | -| | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Data services are useful for searching and querying data from Elasticsearch. Helpful utilities include: a re-usable react query bar, KQL autocomplete, async search, Data Views (Index Patterns) and field formatters. | 3131 | 34 | 2441 | 23 | +| | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Data services are useful for searching and querying data from Elasticsearch. Helpful utilities include: a re-usable react query bar, KQL autocomplete, async search, Data Views (Index Patterns) and field formatters. | 3144 | 34 | 2444 | 23 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | This plugin provides the ability to create data views via a modal flyout inside Kibana apps | 15 | 0 | 7 | 0 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Reusable data view field editor across Kibana | 49 | 0 | 29 | 3 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Data view management app | 2 | 0 | 2 | 0 | @@ -60,7 +60,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Platform Security](https://github.com/orgs/elastic/teams/kibana-security) | This plugin provides encryption and decryption utilities for saved objects containing sensitive information. | 51 | 0 | 42 | 0 | | | [Enterprise Search](https://github.com/orgs/elastic/teams/enterprise-search-frontend) | Adds dashboards for discovering and managing Enterprise Search products. | 8 | 0 | 8 | 0 | | | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 114 | 3 | 110 | 3 | -| | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | The Event Annotation service contains expressions for event annotations | 163 | 0 | 163 | 5 | +| | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | The Event Annotation service contains expressions for event annotations | 170 | 0 | 170 | 3 | | | [Response Ops](https://github.com/orgs/elastic/teams/response-ops) | - | 100 | 0 | 100 | 9 | | | [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds 'error' renderer to expressions | 17 | 0 | 15 | 2 | | | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Expression Gauge plugin adds a `gauge` renderer and function to the expression plugin. The renderer will display the `gauge` chart. | 57 | 0 | 57 | 2 | @@ -74,13 +74,13 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds 'revealImage' function and renderer to expressions | 14 | 0 | 14 | 3 | | | [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds 'shape' function and renderer to expressions | 148 | 0 | 146 | 0 | | | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Expression Tagcloud plugin adds a `tagcloud` renderer and function to the expression plugin. The renderer will display the `Wordcloud` chart. | 7 | 0 | 7 | 0 | -| | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Expression XY plugin adds a `xy` renderer and function to the expression plugin. The renderer will display the `xy` chart. | 152 | 0 | 142 | 11 | +| | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Expression XY plugin adds a `xy` renderer and function to the expression plugin. The renderer will display the `xy` chart. | 153 | 0 | 142 | 9 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Adds expression runtime to Kibana | 2183 | 17 | 1729 | 5 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 222 | 0 | 95 | 2 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Index pattern fields and ambiguous values formatters | 288 | 5 | 249 | 3 | | | [Machine Learning UI](https://github.com/orgs/elastic/teams/ml-ui) | The file upload plugin contains components and services for uploading a file, analyzing its data, and then importing the data into an Elasticsearch index. Supported file types include CSV, TSV, newline-delimited JSON and GeoJSON. | 62 | 0 | 62 | 2 | | | [@elastic/kibana-app-services](https://github.com/orgs/elastic/teams/team:AppServicesUx) | File upload, download, sharing, and serving over HTTP implementation in Kibana. | 240 | 0 | 6 | 2 | -| | [Fleet](https://github.com/orgs/elastic/teams/fleet) | - | 969 | 3 | 873 | 10 | +| | [Fleet](https://github.com/orgs/elastic/teams/fleet) | - | 970 | 3 | 873 | 10 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 68 | 0 | 14 | 5 | | globalSearchBar | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 0 | 0 | 0 | 0 | | globalSearchProviders | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 0 | 0 | 0 | 0 | @@ -99,7 +99,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | kibanaUsageCollection | [Kibana Telemetry](https://github.com/orgs/elastic/teams/kibana-telemetry) | - | 0 | 0 | 0 | 0 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | - | 615 | 3 | 418 | 9 | | | [Security Team](https://github.com/orgs/elastic/teams/security-team) | - | 3 | 0 | 3 | 1 | -| | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Visualization editor allowing to quickly and easily configure compelling visualizations to use on dashboards and canvas workpads. Exposes components to embed visualizations and link into the Lens editor from within other apps in Kibana. | 619 | 0 | 533 | 41 | +| | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Visualization editor allowing to quickly and easily configure compelling visualizations to use on dashboards and canvas workpads. Exposes components to embed visualizations and link into the Lens editor from within other apps in Kibana. | 639 | 0 | 550 | 41 | | | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 8 | 0 | 8 | 0 | | | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 3 | 0 | 3 | 0 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 117 | 0 | 42 | 10 | @@ -126,7 +126,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 16 | 0 | 16 | 0 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 130 | 0 | 117 | 0 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 78 | 0 | 72 | 3 | -| | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 91 | 0 | 46 | 1 | +| | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 94 | 0 | 47 | 1 | | | [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | This plugin contains the definition and helper methods around saved searches, used by discover and visualizations. | 43 | 0 | 43 | 1 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | - | 32 | 0 | 13 | 0 | | | [Kibana Reporting Services](https://github.com/orgs/elastic/teams/kibana-reporting-services) | Kibana Screenshotting Plugin | 27 | 0 | 8 | 4 | @@ -151,8 +151,8 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Response Ops](https://github.com/orgs/elastic/teams/response-ops) | - | 428 | 0 | 407 | 46 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Adds UI Actions service to Kibana | 132 | 0 | 91 | 11 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Extends UI Actions plugin with more functionality | 205 | 0 | 142 | 9 | -| | [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | Contains functionality for the field list which can be integrated into apps | 51 | 0 | 49 | 2 | -| | [Unified Search](https://github.com/orgs/elastic/teams/kibana-app-services) | Contains all the key functionality of Kibana's unified search experience.Contains all the key functionality of Kibana's unified search experience. | 109 | 2 | 84 | 16 | +| | [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | Contains functionality for the field list which can be integrated into apps | 54 | 0 | 52 | 2 | +| | [Unified Search](https://github.com/orgs/elastic/teams/kibana-app-services) | Contains all the key functionality of Kibana's unified search experience.Contains all the key functionality of Kibana's unified search experience. | 111 | 2 | 85 | 16 | | upgradeAssistant | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 0 | 0 | 0 | 0 | | urlDrilldown | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Adds drilldown implementations to Kibana | 0 | 0 | 0 | 0 | | | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | - | 12 | 0 | 12 | 0 | @@ -171,7 +171,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Registers the vega visualization. Is the elastic version of vega and vega-lite libraries. | 2 | 0 | 2 | 0 | | | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Contains the vislib visualizations. These are the classical area/line/bar, pie, gauge/goal and heatmap charts. We want to replace them with elastic-charts. | 26 | 0 | 25 | 1 | | | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Contains the new xy-axis chart using the elastic-charts library, which will eventually replace the vislib xy-axis charts including bar, area, and line. | 53 | 0 | 50 | 5 | -| | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Contains the shared architecture among all the legacy visualizations, e.g. the visualization type registry or the visualization embeddable. | 417 | 12 | 389 | 15 | +| | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Contains the shared architecture among all the legacy visualizations, e.g. the visualization type registry or the visualization embeddable. | 419 | 12 | 390 | 15 | | watcher | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 0 | 0 | 0 | 0 | ## Package Directory @@ -346,8 +346,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | App Services | - | 35 | 4 | 35 | 0 | | | [Owner missing] | - | 20 | 0 | 20 | 2 | | | [Owner missing] | - | 13 | 0 | 13 | 0 | -| | [Owner missing] | - | 7 | 0 | 4 | 3 | -| | [Owner missing] | - | 91 | 0 | 91 | 0 | +| | [Owner missing] | - | 97 | 0 | 96 | 0 | | | Kibana Core | - | 30 | 0 | 5 | 37 | | | Kibana Core | - | 8 | 0 | 8 | 0 | | | [Owner missing] | - | 6 | 0 | 1 | 1 | @@ -368,12 +367,12 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Owner missing] | security solution elastic search utilities to use across plugins such lists, security_solution, cases, etc... | 67 | 0 | 61 | 1 | | | [Owner missing] | Security Solution utilities for React hooks | 15 | 0 | 7 | 0 | | | [Owner missing] | io ts utilities and types to be shared with plugins from the security solution project | 148 | 0 | 129 | 0 | -| | [Owner missing] | io ts utilities and types to be shared with plugins from the security solution project | 462 | 1 | 449 | 0 | +| | [Owner missing] | io ts utilities and types to be shared with plugins from the security solution project | 470 | 1 | 457 | 0 | | | [Owner missing] | io ts utilities and types to be shared with plugins from the security solution project | 61 | 0 | 32 | 0 | | | [Owner missing] | io ts utilities and types to be shared with plugins from the security solution project | 28 | 0 | 21 | 0 | | | [Owner missing] | security solution list REST API | 61 | 0 | 60 | 0 | -| | [Owner missing] | security solution list constants to use across plugins such lists, security_solution, cases, etc... | 26 | 0 | 12 | 0 | -| | [Owner missing] | Security solution list ReactJS hooks | 56 | 0 | 44 | 0 | +| | [Owner missing] | security solution list constants to use across plugins such lists, security_solution, cases, etc... | 28 | 0 | 13 | 0 | +| | [Owner missing] | Security solution list ReactJS hooks | 53 | 0 | 42 | 0 | | | [Owner missing] | security solution list utilities | 235 | 0 | 187 | 0 | | | [Owner missing] | security solution rule utilities to use across plugins | 26 | 0 | 23 | 0 | | | [Owner missing] | security solution t-grid packages will allow sharing components between timelines and security_solution plugin until we transfer all functionality to timelines plugin | 120 | 0 | 116 | 0 | diff --git a/api_docs/presentation_util.mdx b/api_docs/presentation_util.mdx index 3ea342705aa796..bd88e5f88c6ffd 100644 --- a/api_docs/presentation_util.mdx +++ b/api_docs/presentation_util.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/presentationUtil title: "presentationUtil" image: https://source.unsplash.com/400x175/?github description: API docs for the presentationUtil plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'presentationUtil'] --- import presentationUtilObj from './presentation_util.devdocs.json'; diff --git a/api_docs/remote_clusters.mdx b/api_docs/remote_clusters.mdx index a3f07005a43474..4dc8865027be98 100644 --- a/api_docs/remote_clusters.mdx +++ b/api_docs/remote_clusters.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/remoteClusters title: "remoteClusters" image: https://source.unsplash.com/400x175/?github description: API docs for the remoteClusters plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'remoteClusters'] --- import remoteClustersObj from './remote_clusters.devdocs.json'; diff --git a/api_docs/reporting.mdx b/api_docs/reporting.mdx index d29a5518fd4dd8..98619fec51a28f 100644 --- a/api_docs/reporting.mdx +++ b/api_docs/reporting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/reporting title: "reporting" image: https://source.unsplash.com/400x175/?github description: API docs for the reporting plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'reporting'] --- import reportingObj from './reporting.devdocs.json'; diff --git a/api_docs/rollup.mdx b/api_docs/rollup.mdx index b7b0340b076654..32c76e983e404c 100644 --- a/api_docs/rollup.mdx +++ b/api_docs/rollup.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/rollup title: "rollup" image: https://source.unsplash.com/400x175/?github description: API docs for the rollup plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'rollup'] --- import rollupObj from './rollup.devdocs.json'; diff --git a/api_docs/rule_registry.mdx b/api_docs/rule_registry.mdx index 086a42a7c8e6c1..0c20752827038f 100644 --- a/api_docs/rule_registry.mdx +++ b/api_docs/rule_registry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ruleRegistry title: "ruleRegistry" image: https://source.unsplash.com/400x175/?github description: API docs for the ruleRegistry plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ruleRegistry'] --- import ruleRegistryObj from './rule_registry.devdocs.json'; diff --git a/api_docs/runtime_fields.mdx b/api_docs/runtime_fields.mdx index 4b03559bc8d9cf..3da2926bef45d4 100644 --- a/api_docs/runtime_fields.mdx +++ b/api_docs/runtime_fields.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/runtimeFields title: "runtimeFields" image: https://source.unsplash.com/400x175/?github description: API docs for the runtimeFields plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'runtimeFields'] --- import runtimeFieldsObj from './runtime_fields.devdocs.json'; diff --git a/api_docs/saved_objects.mdx b/api_docs/saved_objects.mdx index 581e5be0e084f7..ccb2436bc7ab51 100644 --- a/api_docs/saved_objects.mdx +++ b/api_docs/saved_objects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjects title: "savedObjects" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjects plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjects'] --- import savedObjectsObj from './saved_objects.devdocs.json'; diff --git a/api_docs/saved_objects_finder.mdx b/api_docs/saved_objects_finder.mdx index d76a6d9879ca88..8ebb9e956a9bd1 100644 --- a/api_docs/saved_objects_finder.mdx +++ b/api_docs/saved_objects_finder.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsFinder title: "savedObjectsFinder" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsFinder plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsFinder'] --- import savedObjectsFinderObj from './saved_objects_finder.devdocs.json'; diff --git a/api_docs/saved_objects_management.mdx b/api_docs/saved_objects_management.mdx index 002ea2800bd028..96fc861f282ecf 100644 --- a/api_docs/saved_objects_management.mdx +++ b/api_docs/saved_objects_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsManagement title: "savedObjectsManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsManagement plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsManagement'] --- import savedObjectsManagementObj from './saved_objects_management.devdocs.json'; diff --git a/api_docs/saved_objects_tagging.mdx b/api_docs/saved_objects_tagging.mdx index d94db5cfbcfc39..f1f07a53b63c0d 100644 --- a/api_docs/saved_objects_tagging.mdx +++ b/api_docs/saved_objects_tagging.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsTagging title: "savedObjectsTagging" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsTagging plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsTagging'] --- import savedObjectsTaggingObj from './saved_objects_tagging.devdocs.json'; diff --git a/api_docs/saved_objects_tagging_oss.devdocs.json b/api_docs/saved_objects_tagging_oss.devdocs.json index 82be777e2094af..31b3bccca32ed6 100644 --- a/api_docs/saved_objects_tagging_oss.devdocs.json +++ b/api_docs/saved_objects_tagging_oss.devdocs.json @@ -52,6 +52,38 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "savedObjectsTaggingOss", + "id": "def-public.GetTableColumnDefinitionOptions", + "type": "Interface", + "tags": [], + "label": "GetTableColumnDefinitionOptions", + "description": [ + "\nOptions for the {@link SavedObjectsTaggingApiUi.getTableColumnDefinition | getTableColumnDefinition api}\n" + ], + "path": "src/plugins/saved_objects_tagging_oss/public/api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "savedObjectsTaggingOss", + "id": "def-public.GetTableColumnDefinitionOptions.serverPaging", + "type": "CompoundType", + "tags": [], + "label": "serverPaging", + "description": [ + "\nBy default, the `tags` column definition will be automatically sortable\nby tag name.\n\nHowever, when paging is performed on the server, we need to remove the sorting\ncapability from the column to avoid unexpected behavior by triggering fetch request\nwhen sorting by column.\n\nShould be set to `true` when generating the definition for a table that performs\nserver-side paging.\n\nDefaults to false." + ], + "signature": [ + "boolean | undefined" + ], + "path": "src/plugins/saved_objects_tagging_oss/public/api.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "savedObjectsTaggingOss", "id": "def-public.ITagsCache", @@ -535,7 +567,15 @@ "\nReturn the column definition to be used to display the tags in a EUI table.\nThe table's items must be of the `SavedObject` type (or at least have their references available\nvia the `references` field)\n" ], "signature": [ - "() => ", + "(options?: ", + { + "pluginId": "savedObjectsTaggingOss", + "scope": "public", + "docId": "kibSavedObjectsTaggingOssPluginApi", + "section": "def-public.GetTableColumnDefinitionOptions", + "text": "GetTableColumnDefinitionOptions" + }, + " | undefined) => ", "EuiTableFieldDataColumnType", "<", "SavedObject", @@ -544,7 +584,30 @@ "path": "src/plugins/saved_objects_tagging_oss/public/api.ts", "deprecated": false, "trackAdoption": false, - "children": [], + "children": [ + { + "parentPluginId": "savedObjectsTaggingOss", + "id": "def-public.SavedObjectsTaggingApiUi.getTableColumnDefinition.$1", + "type": "Object", + "tags": [], + "label": "options", + "description": [], + "signature": [ + { + "pluginId": "savedObjectsTaggingOss", + "scope": "public", + "docId": "kibSavedObjectsTaggingOssPluginApi", + "section": "def-public.GetTableColumnDefinitionOptions", + "text": "GetTableColumnDefinitionOptions" + }, + " | undefined" + ], + "path": "src/plugins/saved_objects_tagging_oss/public/api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], "returnComment": [] }, { diff --git a/api_docs/saved_objects_tagging_oss.mdx b/api_docs/saved_objects_tagging_oss.mdx index a2df3e4349d08d..10469dabcc739c 100644 --- a/api_docs/saved_objects_tagging_oss.mdx +++ b/api_docs/saved_objects_tagging_oss.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsTaggingOss title: "savedObjectsTaggingOss" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsTaggingOss plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsTaggingOss'] --- import savedObjectsTaggingOssObj from './saved_objects_tagging_oss.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) for que | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 91 | 0 | 46 | 1 | +| 94 | 0 | 47 | 1 | ## Client diff --git a/api_docs/saved_search.mdx b/api_docs/saved_search.mdx index b5e7da8db88509..e0fd13863fddb3 100644 --- a/api_docs/saved_search.mdx +++ b/api_docs/saved_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedSearch title: "savedSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the savedSearch plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedSearch'] --- import savedSearchObj from './saved_search.devdocs.json'; diff --git a/api_docs/screenshot_mode.mdx b/api_docs/screenshot_mode.mdx index 38322a98b68989..ab9308881edad5 100644 --- a/api_docs/screenshot_mode.mdx +++ b/api_docs/screenshot_mode.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/screenshotMode title: "screenshotMode" image: https://source.unsplash.com/400x175/?github description: API docs for the screenshotMode plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotMode'] --- import screenshotModeObj from './screenshot_mode.devdocs.json'; diff --git a/api_docs/screenshotting.mdx b/api_docs/screenshotting.mdx index 390350e5434094..25835a28fb913b 100644 --- a/api_docs/screenshotting.mdx +++ b/api_docs/screenshotting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/screenshotting title: "screenshotting" image: https://source.unsplash.com/400x175/?github description: API docs for the screenshotting plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotting'] --- import screenshottingObj from './screenshotting.devdocs.json'; diff --git a/api_docs/security.mdx b/api_docs/security.mdx index a9943df56bf6d6..7aeaddd49f9fc2 100644 --- a/api_docs/security.mdx +++ b/api_docs/security.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/security title: "security" image: https://source.unsplash.com/400x175/?github description: API docs for the security plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'security'] --- import securityObj from './security.devdocs.json'; diff --git a/api_docs/security_solution.mdx b/api_docs/security_solution.mdx index 751f29fcd86f2d..f2e9de3b4461d9 100644 --- a/api_docs/security_solution.mdx +++ b/api_docs/security_solution.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/securitySolution title: "securitySolution" image: https://source.unsplash.com/400x175/?github description: API docs for the securitySolution plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolution'] --- import securitySolutionObj from './security_solution.devdocs.json'; diff --git a/api_docs/session_view.mdx b/api_docs/session_view.mdx index 102df49e16bd0c..a0b46b34aff8c2 100644 --- a/api_docs/session_view.mdx +++ b/api_docs/session_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/sessionView title: "sessionView" image: https://source.unsplash.com/400x175/?github description: API docs for the sessionView plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'sessionView'] --- import sessionViewObj from './session_view.devdocs.json'; diff --git a/api_docs/share.mdx b/api_docs/share.mdx index 2d2bb4aeb954b3..917ac7b5c8b7aa 100644 --- a/api_docs/share.mdx +++ b/api_docs/share.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/share title: "share" image: https://source.unsplash.com/400x175/?github description: API docs for the share plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'share'] --- import shareObj from './share.devdocs.json'; diff --git a/api_docs/snapshot_restore.mdx b/api_docs/snapshot_restore.mdx index 801a73732f10fb..3d2d4e9f7d91bb 100644 --- a/api_docs/snapshot_restore.mdx +++ b/api_docs/snapshot_restore.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/snapshotRestore title: "snapshotRestore" image: https://source.unsplash.com/400x175/?github description: API docs for the snapshotRestore plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'snapshotRestore'] --- import snapshotRestoreObj from './snapshot_restore.devdocs.json'; diff --git a/api_docs/spaces.mdx b/api_docs/spaces.mdx index 04a2b91499bc92..039252a8b5f89e 100644 --- a/api_docs/spaces.mdx +++ b/api_docs/spaces.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/spaces title: "spaces" image: https://source.unsplash.com/400x175/?github description: API docs for the spaces plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'spaces'] --- import spacesObj from './spaces.devdocs.json'; diff --git a/api_docs/stack_alerts.mdx b/api_docs/stack_alerts.mdx index a7267f334ac244..e1bbb20979c05e 100644 --- a/api_docs/stack_alerts.mdx +++ b/api_docs/stack_alerts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/stackAlerts title: "stackAlerts" image: https://source.unsplash.com/400x175/?github description: API docs for the stackAlerts plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'stackAlerts'] --- import stackAlertsObj from './stack_alerts.devdocs.json'; diff --git a/api_docs/task_manager.mdx b/api_docs/task_manager.mdx index afeaaa23f957b6..6f5a5d420ec861 100644 --- a/api_docs/task_manager.mdx +++ b/api_docs/task_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/taskManager title: "taskManager" image: https://source.unsplash.com/400x175/?github description: API docs for the taskManager plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'taskManager'] --- import taskManagerObj from './task_manager.devdocs.json'; diff --git a/api_docs/telemetry.mdx b/api_docs/telemetry.mdx index 9d26a0797fc9a0..fe725f5cd654d4 100644 --- a/api_docs/telemetry.mdx +++ b/api_docs/telemetry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetry title: "telemetry" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetry plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetry'] --- import telemetryObj from './telemetry.devdocs.json'; diff --git a/api_docs/telemetry_collection_manager.mdx b/api_docs/telemetry_collection_manager.mdx index fa4a84d009b7e2..c510c72159d824 100644 --- a/api_docs/telemetry_collection_manager.mdx +++ b/api_docs/telemetry_collection_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryCollectionManager title: "telemetryCollectionManager" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryCollectionManager plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryCollectionManager'] --- import telemetryCollectionManagerObj from './telemetry_collection_manager.devdocs.json'; diff --git a/api_docs/telemetry_collection_xpack.mdx b/api_docs/telemetry_collection_xpack.mdx index c17d37ef70fe99..79bcdf8736b5d0 100644 --- a/api_docs/telemetry_collection_xpack.mdx +++ b/api_docs/telemetry_collection_xpack.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryCollectionXpack title: "telemetryCollectionXpack" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryCollectionXpack plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryCollectionXpack'] --- import telemetryCollectionXpackObj from './telemetry_collection_xpack.devdocs.json'; diff --git a/api_docs/telemetry_management_section.mdx b/api_docs/telemetry_management_section.mdx index c3278ea2f27b35..a79d78af7bd71b 100644 --- a/api_docs/telemetry_management_section.mdx +++ b/api_docs/telemetry_management_section.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryManagementSection title: "telemetryManagementSection" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryManagementSection plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryManagementSection'] --- import telemetryManagementSectionObj from './telemetry_management_section.devdocs.json'; diff --git a/api_docs/threat_intelligence.mdx b/api_docs/threat_intelligence.mdx index c2cf26e1f13b81..5a830485f55ec6 100644 --- a/api_docs/threat_intelligence.mdx +++ b/api_docs/threat_intelligence.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/threatIntelligence title: "threatIntelligence" image: https://source.unsplash.com/400x175/?github description: API docs for the threatIntelligence plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'threatIntelligence'] --- import threatIntelligenceObj from './threat_intelligence.devdocs.json'; diff --git a/api_docs/timelines.devdocs.json b/api_docs/timelines.devdocs.json index 26500b5d7f8388..72a30421386dfc 100644 --- a/api_docs/timelines.devdocs.json +++ b/api_docs/timelines.devdocs.json @@ -6453,7 +6453,7 @@ }, " extends Omit<", "TimelineRequestBasicOptions", - ", \"timerange\" | \"filterQuery\" | \"runtimeMappings\">" + ", \"timerange\" | \"runtimeMappings\" | \"filterQuery\">" ], "path": "x-pack/plugins/timelines/common/search_strategy/timeline/events/last_event_time/index.ts", "deprecated": false, diff --git a/api_docs/timelines.mdx b/api_docs/timelines.mdx index 4c98cbb2f255b3..e8be0345a839ff 100644 --- a/api_docs/timelines.mdx +++ b/api_docs/timelines.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/timelines title: "timelines" image: https://source.unsplash.com/400x175/?github description: API docs for the timelines plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'timelines'] --- import timelinesObj from './timelines.devdocs.json'; diff --git a/api_docs/transform.mdx b/api_docs/transform.mdx index c76bdf57b2d843..d53e2f51177d78 100644 --- a/api_docs/transform.mdx +++ b/api_docs/transform.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/transform title: "transform" image: https://source.unsplash.com/400x175/?github description: API docs for the transform plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'transform'] --- import transformObj from './transform.devdocs.json'; diff --git a/api_docs/triggers_actions_ui.mdx b/api_docs/triggers_actions_ui.mdx index d1650d2cc1758b..97a09460258c2e 100644 --- a/api_docs/triggers_actions_ui.mdx +++ b/api_docs/triggers_actions_ui.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/triggersActionsUi title: "triggersActionsUi" image: https://source.unsplash.com/400x175/?github description: API docs for the triggersActionsUi plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'triggersActionsUi'] --- import triggersActionsUiObj from './triggers_actions_ui.devdocs.json'; diff --git a/api_docs/ui_actions.mdx b/api_docs/ui_actions.mdx index 2ca1ebc6639851..e95f3879bfb834 100644 --- a/api_docs/ui_actions.mdx +++ b/api_docs/ui_actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uiActions title: "uiActions" image: https://source.unsplash.com/400x175/?github description: API docs for the uiActions plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActions'] --- import uiActionsObj from './ui_actions.devdocs.json'; diff --git a/api_docs/ui_actions_enhanced.mdx b/api_docs/ui_actions_enhanced.mdx index f498da6aab5525..477dcd64c4e87e 100644 --- a/api_docs/ui_actions_enhanced.mdx +++ b/api_docs/ui_actions_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uiActionsEnhanced title: "uiActionsEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the uiActionsEnhanced plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActionsEnhanced'] --- import uiActionsEnhancedObj from './ui_actions_enhanced.devdocs.json'; diff --git a/api_docs/unified_field_list.devdocs.json b/api_docs/unified_field_list.devdocs.json index 43c861319fd044..e7555c2ac5a6c7 100644 --- a/api_docs/unified_field_list.devdocs.json +++ b/api_docs/unified_field_list.devdocs.json @@ -57,6 +57,39 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.loadFieldExisting", + "type": "Function", + "tags": [], + "label": "loadFieldExisting", + "description": [], + "signature": [ + "({\n data,\n dslQuery,\n fromDate,\n toDate,\n timeFieldName,\n dataViewsService,\n uiSettingsClient,\n dataView,\n}: FetchFieldExistenceParams) => Promise<{ indexPatternTitle: string; existingFieldNames: string[]; }>" + ], + "path": "src/plugins/unified_field_list/public/services/field_existing/load_field_existing.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.loadFieldExisting.$1", + "type": "Object", + "tags": [], + "label": "{\n data,\n dslQuery,\n fromDate,\n toDate,\n timeFieldName,\n dataViewsService,\n uiSettingsClient,\n dataView,\n}", + "description": [], + "signature": [ + "FetchFieldExistenceParams" + ], + "path": "src/plugins/unified_field_list/public/services/field_existing/load_field_existing.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "unifiedFieldList", "id": "def-public.loadFieldStats", @@ -810,6 +843,21 @@ "interfaces": [], "enums": [], "misc": [ + { + "parentPluginId": "unifiedFieldList", + "id": "def-common.FIELD_EXISTENCE_SETTING", + "type": "string", + "tags": [], + "label": "FIELD_EXISTENCE_SETTING", + "description": [], + "signature": [ + "\"lens:useFieldExistenceSampling\"" + ], + "path": "src/plugins/unified_field_list/common/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "unifiedFieldList", "id": "def-common.PLUGIN_ID", diff --git a/api_docs/unified_field_list.mdx b/api_docs/unified_field_list.mdx index 2fb8a110a05eb2..f2fbbc473c25c0 100644 --- a/api_docs/unified_field_list.mdx +++ b/api_docs/unified_field_list.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedFieldList title: "unifiedFieldList" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedFieldList plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedFieldList'] --- import unifiedFieldListObj from './unified_field_list.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-disco | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 51 | 0 | 49 | 2 | +| 54 | 0 | 52 | 2 | ## Client diff --git a/api_docs/unified_search.devdocs.json b/api_docs/unified_search.devdocs.json index 0edb9ef43d4360..909ff5f2d26f2c 100644 --- a/api_docs/unified_search.devdocs.json +++ b/api_docs/unified_search.devdocs.json @@ -11,7 +11,7 @@ "label": "DataViewPicker", "description": [], "signature": [ - "({ isMissingCurrent, currentDataViewId, adHocDataViews, onChangeDataView, onAddField, onDataViewCreated, trigger, selectableProps, textBasedLanguages, onSaveTextLanguageQuery, onTextLangQuerySubmit, textBasedLanguage, }: ", + "({ isMissingCurrent, currentDataViewId, adHocDataViews, onChangeDataView, onAddField, onDataViewCreated, trigger, selectableProps, textBasedLanguages, onSaveTextLanguageQuery, onTextLangQuerySubmit, textBasedLanguage, isDisabled, }: ", "DataViewPickerPropsExtended", ") => JSX.Element" ], @@ -24,7 +24,7 @@ "id": "def-public.DataViewPicker.$1", "type": "Object", "tags": [], - "label": "{\n isMissingCurrent,\n currentDataViewId,\n adHocDataViews,\n onChangeDataView,\n onAddField,\n onDataViewCreated,\n trigger,\n selectableProps,\n textBasedLanguages,\n onSaveTextLanguageQuery,\n onTextLangQuerySubmit,\n textBasedLanguage,\n}", + "label": "{\n isMissingCurrent,\n currentDataViewId,\n adHocDataViews,\n onChangeDataView,\n onAddField,\n onDataViewCreated,\n trigger,\n selectableProps,\n textBasedLanguages,\n onSaveTextLanguageQuery,\n onTextLangQuerySubmit,\n textBasedLanguage,\n isDisabled,\n}", "description": [], "signature": [ "DataViewPickerPropsExtended" @@ -320,7 +320,7 @@ "section": "def-common.DataView", "text": "DataView" }, - "[] | undefined; isLoading?: boolean | undefined; timeHistory?: ", + "[] | undefined; isDisabled?: boolean | undefined; isLoading?: boolean | undefined; timeHistory?: ", { "pluginId": "data", "scope": "public", @@ -697,6 +697,22 @@ } ], "returnComment": [] + }, + { + "parentPluginId": "unifiedSearch", + "id": "def-public.DataViewPickerProps.isDisabled", + "type": "CompoundType", + "tags": [], + "label": "isDisabled", + "description": [ + "\nMakes the picker disabled by disabling the popover trigger" + ], + "signature": [ + "boolean | undefined" + ], + "path": "src/plugins/unified_search/public/dataview_picker/index.tsx", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -1241,6 +1257,20 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "unifiedSearch", + "id": "def-public.QueryStringInputProps.isDisabled", + "type": "CompoundType", + "tags": [], + "label": "isDisabled", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "src/plugins/unified_search/public/query_string_input/query_string_input.tsx", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "unifiedSearch", "id": "def-public.QueryStringInputProps.nonKqlMode", diff --git a/api_docs/unified_search.mdx b/api_docs/unified_search.mdx index fc96cbb1e9cc09..c14315f59ce5ab 100644 --- a/api_docs/unified_search.mdx +++ b/api_docs/unified_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedSearch title: "unifiedSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedSearch plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedSearch'] --- import unifiedSearchObj from './unified_search.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Unified Search](https://github.com/orgs/elastic/teams/kibana-app-servic | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 109 | 2 | 84 | 16 | +| 111 | 2 | 85 | 16 | ## Client diff --git a/api_docs/unified_search_autocomplete.mdx b/api_docs/unified_search_autocomplete.mdx index 34c1ea2a1354d4..74c9ed470c1f10 100644 --- a/api_docs/unified_search_autocomplete.mdx +++ b/api_docs/unified_search_autocomplete.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedSearch-autocomplete title: "unifiedSearch.autocomplete" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedSearch.autocomplete plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedSearch.autocomplete'] --- import unifiedSearchAutocompleteObj from './unified_search_autocomplete.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Unified Search](https://github.com/orgs/elastic/teams/kibana-app-servic | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 109 | 2 | 84 | 16 | +| 111 | 2 | 85 | 16 | ## Client diff --git a/api_docs/url_forwarding.mdx b/api_docs/url_forwarding.mdx index 8a99fa786b1508..b9c921a284d1d1 100644 --- a/api_docs/url_forwarding.mdx +++ b/api_docs/url_forwarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/urlForwarding title: "urlForwarding" image: https://source.unsplash.com/400x175/?github description: API docs for the urlForwarding plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'urlForwarding'] --- import urlForwardingObj from './url_forwarding.devdocs.json'; diff --git a/api_docs/usage_collection.mdx b/api_docs/usage_collection.mdx index 953cdbc32149c1..4de9f1cf325bfd 100644 --- a/api_docs/usage_collection.mdx +++ b/api_docs/usage_collection.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/usageCollection title: "usageCollection" image: https://source.unsplash.com/400x175/?github description: API docs for the usageCollection plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'usageCollection'] --- import usageCollectionObj from './usage_collection.devdocs.json'; diff --git a/api_docs/ux.mdx b/api_docs/ux.mdx index 3016625362ce12..d497f6bb0a4466 100644 --- a/api_docs/ux.mdx +++ b/api_docs/ux.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ux title: "ux" image: https://source.unsplash.com/400x175/?github description: API docs for the ux plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ux'] --- import uxObj from './ux.devdocs.json'; diff --git a/api_docs/vis_default_editor.mdx b/api_docs/vis_default_editor.mdx index ff8015da299faa..1237c1960ae3bd 100644 --- a/api_docs/vis_default_editor.mdx +++ b/api_docs/vis_default_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visDefaultEditor title: "visDefaultEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the visDefaultEditor plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visDefaultEditor'] --- import visDefaultEditorObj from './vis_default_editor.devdocs.json'; diff --git a/api_docs/vis_type_gauge.mdx b/api_docs/vis_type_gauge.mdx index ff9ff105efb1a6..54d7da6ff41a93 100644 --- a/api_docs/vis_type_gauge.mdx +++ b/api_docs/vis_type_gauge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeGauge title: "visTypeGauge" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeGauge plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeGauge'] --- import visTypeGaugeObj from './vis_type_gauge.devdocs.json'; diff --git a/api_docs/vis_type_heatmap.mdx b/api_docs/vis_type_heatmap.mdx index f5265c4edc969f..48c4485641f9b5 100644 --- a/api_docs/vis_type_heatmap.mdx +++ b/api_docs/vis_type_heatmap.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeHeatmap title: "visTypeHeatmap" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeHeatmap plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeHeatmap'] --- import visTypeHeatmapObj from './vis_type_heatmap.devdocs.json'; diff --git a/api_docs/vis_type_pie.mdx b/api_docs/vis_type_pie.mdx index fc9bf5001a2ced..f03b8bea14f0b6 100644 --- a/api_docs/vis_type_pie.mdx +++ b/api_docs/vis_type_pie.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypePie title: "visTypePie" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypePie plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypePie'] --- import visTypePieObj from './vis_type_pie.devdocs.json'; diff --git a/api_docs/vis_type_table.mdx b/api_docs/vis_type_table.mdx index 0971c9d2d784dd..db63128f3733ec 100644 --- a/api_docs/vis_type_table.mdx +++ b/api_docs/vis_type_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTable title: "visTypeTable" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTable plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTable'] --- import visTypeTableObj from './vis_type_table.devdocs.json'; diff --git a/api_docs/vis_type_timelion.mdx b/api_docs/vis_type_timelion.mdx index 1601dd0ca05b04..3767eed28f79c3 100644 --- a/api_docs/vis_type_timelion.mdx +++ b/api_docs/vis_type_timelion.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTimelion title: "visTypeTimelion" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTimelion plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTimelion'] --- import visTypeTimelionObj from './vis_type_timelion.devdocs.json'; diff --git a/api_docs/vis_type_timeseries.mdx b/api_docs/vis_type_timeseries.mdx index 4442ae6bcf5914..eaa8be6fe9eaa5 100644 --- a/api_docs/vis_type_timeseries.mdx +++ b/api_docs/vis_type_timeseries.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTimeseries title: "visTypeTimeseries" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTimeseries plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTimeseries'] --- import visTypeTimeseriesObj from './vis_type_timeseries.devdocs.json'; diff --git a/api_docs/vis_type_vega.mdx b/api_docs/vis_type_vega.mdx index 9804c7468413e7..56642da0d7bb1d 100644 --- a/api_docs/vis_type_vega.mdx +++ b/api_docs/vis_type_vega.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeVega title: "visTypeVega" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeVega plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeVega'] --- import visTypeVegaObj from './vis_type_vega.devdocs.json'; diff --git a/api_docs/vis_type_vislib.mdx b/api_docs/vis_type_vislib.mdx index 0f5bedc6073f30..20e284f805f36e 100644 --- a/api_docs/vis_type_vislib.mdx +++ b/api_docs/vis_type_vislib.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeVislib title: "visTypeVislib" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeVislib plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeVislib'] --- import visTypeVislibObj from './vis_type_vislib.devdocs.json'; diff --git a/api_docs/vis_type_xy.mdx b/api_docs/vis_type_xy.mdx index a9531484ea581e..d7a9c73ca02656 100644 --- a/api_docs/vis_type_xy.mdx +++ b/api_docs/vis_type_xy.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeXy title: "visTypeXy" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeXy plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeXy'] --- import visTypeXyObj from './vis_type_xy.devdocs.json'; diff --git a/api_docs/visualizations.devdocs.json b/api_docs/visualizations.devdocs.json index dffacde50d651b..352226b8a79ff4 100644 --- a/api_docs/visualizations.devdocs.json +++ b/api_docs/visualizations.devdocs.json @@ -276,6 +276,20 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "visualizations", + "id": "def-public.BaseVisType.suppressWarnings", + "type": "Function", + "tags": [], + "label": "suppressWarnings", + "description": [], + "signature": [ + "(() => boolean) | undefined" + ], + "path": "src/plugins/visualizations/public/vis_types/base_vis_type.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "visualizations", "id": "def-public.BaseVisType.hasPartialRows", @@ -4785,6 +4799,24 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "visualizations", + "id": "def-public.VisTypeDefinition.suppressWarnings", + "type": "Function", + "tags": [], + "label": "suppressWarnings", + "description": [ + "\nIf returns true, no warning toasts will be shown" + ], + "signature": [ + "(() => boolean) | undefined" + ], + "path": "src/plugins/visualizations/public/vis_types/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, { "parentPluginId": "visualizations", "id": "def-public.VisTypeDefinition.group", diff --git a/api_docs/visualizations.mdx b/api_docs/visualizations.mdx index 5229d1a341157d..d708564591c581 100644 --- a/api_docs/visualizations.mdx +++ b/api_docs/visualizations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visualizations title: "visualizations" image: https://source.unsplash.com/400x175/?github description: API docs for the visualizations plugin -date: 2022-09-08 +date: 2022-09-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visualizations'] --- import visualizationsObj from './visualizations.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 417 | 12 | 389 | 15 | +| 419 | 12 | 390 | 15 | ## Client diff --git a/dev_docs/contributing/code_walkthrough.mdx b/dev_docs/contributing/code_walkthrough.mdx index bae394887c20ef..617b54e519f139 100644 --- a/dev_docs/contributing/code_walkthrough.mdx +++ b/dev_docs/contributing/code_walkthrough.mdx @@ -21,7 +21,7 @@ Managed by the operations team to contain Jenkins settings. Can be ignored by fo ## [.github](https://github.com/elastic/kibana/tree/main/.github) -Contains GitHub configuration settings. This file contains issue templates, and the [CODEOWNERS](https://github.com/elastic/kibana/blob/main/.github/CODEOWNERS) file. It's important for teams to keep the CODEOWNERS file up-to-date so the right team is pinged for a code owner review on PRs that edit certain files. Note that the `CODEOWNERS` file only exists on the main branch, and is not backported to other branches in the repo. +Contains GitHub configuration settings. This file contains issue templates, and the [CODEOWNERS](https://github.com/elastic/kibana/blob/main/.github/CODEOWNERS) file. It's important for teams to keep the CODEOWNERS file up-to-date so the right team is pinged for a code owner review on PRs that edit certain files. Note that the `CODEOWNERS` file only exists on the main branch, and is not backported to other branches in the repo. To aid in making sure the `CODEOWNERS` file is always up-to-date "packages" in the Kibana repo are required to have an "owner" defined, those owners are then injected into the CODEOWNERS files automatically by the `node scripts/generate codeowners` command. ## [api_docs](https://github.com/elastic/kibana/tree/main/api_docs) diff --git a/kbn_pm/src/commands/run_in_packages_command.mjs b/kbn_pm/src/commands/run_in_packages_command.mjs index 78a168463e6db8..7106722237e6e2 100644 --- a/kbn_pm/src/commands/run_in_packages_command.mjs +++ b/kbn_pm/src/commands/run_in_packages_command.mjs @@ -41,11 +41,11 @@ export const command = { const { discoverBazelPackages } = await import('@kbn/bazel-packages'); const packages = await discoverBazelPackages(REPO_ROOT); - for (const { pkg, normalizedRepoRelativeDir } of packages) { + for (const { manifest, pkg, normalizedRepoRelativeDir } of packages) { if ( - exclude.includes(pkg.name) || - (include.length && !include.includes(pkg.name)) || - !pkg.scripts || + exclude.includes(manifest.id) || + (include.length && !include.includes(manifest.id)) || + !pkg?.scripts || !Object.hasOwn(pkg.scripts, scriptName) ) { continue; diff --git a/package.json b/package.json index 92dc1590d9a512..ae40de1b204f41 100644 --- a/package.json +++ b/package.json @@ -105,7 +105,7 @@ "@dnd-kit/utilities": "^2.0.0", "@elastic/apm-rum": "^5.12.0", "@elastic/apm-rum-react": "^1.4.2", - "@elastic/charts": "48.0.0", + "@elastic/charts": "48.0.1", "@elastic/datemath": "5.0.3", "@elastic/elasticsearch": "npm:@elastic/elasticsearch-canary@8.3.0-canary.1", "@elastic/ems-client": "8.3.3", @@ -140,7 +140,6 @@ "@kbn/analytics-shippers-elastic-v3-server": "link:bazel-bin/packages/analytics/shippers/elastic_v3/server", "@kbn/analytics-shippers-fullstory": "link:bazel-bin/packages/analytics/shippers/fullstory", "@kbn/apm-config-loader": "link:bazel-bin/packages/kbn-apm-config-loader", - "@kbn/apm-synthtrace": "link:bazel-bin/packages/kbn-apm-synthtrace", "@kbn/apm-utils": "link:bazel-bin/packages/kbn-apm-utils", "@kbn/chart-icons": "link:bazel-bin/packages/kbn-chart-icons", "@kbn/coloring": "link:bazel-bin/packages/kbn-coloring", @@ -270,6 +269,11 @@ "@kbn/core-saved-objects-server-internal": "link:bazel-bin/packages/core/saved-objects/core-saved-objects-server-internal", "@kbn/core-saved-objects-server-mocks": "link:bazel-bin/packages/core/saved-objects/core-saved-objects-server-mocks", "@kbn/core-saved-objects-utils-server": "link:bazel-bin/packages/core/saved-objects/core-saved-objects-utils-server", + "@kbn/core-status-common": "link:bazel-bin/packages/core/status/core-status-common", + "@kbn/core-status-common-internal": "link:bazel-bin/packages/core/status/core-status-common-internal", + "@kbn/core-status-server": "link:bazel-bin/packages/core/status/core-status-server", + "@kbn/core-status-server-internal": "link:bazel-bin/packages/core/status/core-status-server-internal", + "@kbn/core-status-server-mocks": "link:bazel-bin/packages/core/status/core-status-server-mocks", "@kbn/core-test-helpers-deprecations-getters": "link:bazel-bin/packages/core/test-helpers/core-test-helpers-deprecations-getters", "@kbn/core-test-helpers-http-setup-browser": "link:bazel-bin/packages/core/test-helpers/core-test-helpers-http-setup-browser", "@kbn/core-theme-browser": "link:bazel-bin/packages/core/theme/core-theme-browser", @@ -290,8 +294,6 @@ "@kbn/ebt-tools": "link:bazel-bin/packages/kbn-ebt-tools", "@kbn/es-errors": "link:bazel-bin/packages/kbn-es-errors", "@kbn/es-query": "link:bazel-bin/packages/kbn-es-query", - "@kbn/eslint-plugin-disable": "link:bazel-bin/packages/kbn-eslint-plugin-disable", - "@kbn/eslint-plugin-imports": "link:bazel-bin/packages/kbn-eslint-plugin-imports", "@kbn/field-types": "link:bazel-bin/packages/kbn-field-types", "@kbn/flot-charts": "link:bazel-bin/packages/kbn-flot-charts", "@kbn/handlebars": "link:bazel-bin/packages/kbn-handlebars", @@ -303,9 +305,6 @@ "@kbn/i18n-react": "link:bazel-bin/packages/kbn-i18n-react", "@kbn/interpreter": "link:bazel-bin/packages/kbn-interpreter", "@kbn/io-ts-utils": "link:bazel-bin/packages/kbn-io-ts-utils", - "@kbn/jsonc": "link:bazel-bin/packages/kbn-jsonc", - "@kbn/kibana-manifest-parser": "link:bazel-bin/packages/kbn-kibana-manifest-parser", - "@kbn/kibana-manifest-schema": "link:bazel-bin/packages/kbn-kibana-manifest-schema", "@kbn/logging": "link:bazel-bin/packages/kbn-logging", "@kbn/logging-mocks": "link:bazel-bin/packages/kbn-logging-mocks", "@kbn/mapbox-gl": "link:bazel-bin/packages/kbn-mapbox-gl", @@ -665,6 +664,7 @@ "@jest/types": "^26", "@kbn/ambient-storybook-types": "link:bazel-bin/packages/kbn-ambient-storybook-types", "@kbn/ambient-ui-types": "link:bazel-bin/packages/kbn-ambient-ui-types", + "@kbn/apm-synthtrace": "link:bazel-bin/packages/kbn-apm-synthtrace", "@kbn/axe-config": "link:bazel-bin/packages/kbn-axe-config", "@kbn/babel-plugin-synthetic-packages": "link:bazel-bin/packages/kbn-babel-plugin-synthetic-packages", "@kbn/babel-preset": "link:bazel-bin/packages/kbn-babel-preset", @@ -682,13 +682,16 @@ "@kbn/es": "link:bazel-bin/packages/kbn-es", "@kbn/es-archiver": "link:bazel-bin/packages/kbn-es-archiver", "@kbn/eslint-config": "link:bazel-bin/packages/kbn-eslint-config", + "@kbn/eslint-plugin-disable": "link:bazel-bin/packages/kbn-eslint-plugin-disable", "@kbn/eslint-plugin-eslint": "link:bazel-bin/packages/kbn-eslint-plugin-eslint", + "@kbn/eslint-plugin-imports": "link:bazel-bin/packages/kbn-eslint-plugin-imports", "@kbn/expect": "link:bazel-bin/packages/kbn-expect", "@kbn/find-used-node-modules": "link:bazel-bin/packages/kbn-find-used-node-modules", "@kbn/generate": "link:bazel-bin/packages/kbn-generate", "@kbn/get-repo-files": "link:bazel-bin/packages/kbn-get-repo-files", "@kbn/import-resolver": "link:bazel-bin/packages/kbn-import-resolver", "@kbn/jest-serializers": "link:bazel-bin/packages/kbn-jest-serializers", + "@kbn/kibana-manifest-schema": "link:bazel-bin/packages/kbn-kibana-manifest-schema", "@kbn/managed-vscode-config": "link:bazel-bin/packages/kbn-managed-vscode-config", "@kbn/managed-vscode-config-cli": "link:bazel-bin/packages/kbn-managed-vscode-config-cli", "@kbn/optimizer": "link:bazel-bin/packages/kbn-optimizer", @@ -958,6 +961,11 @@ "@types/kbn__core-saved-objects-server-mocks": "link:bazel-bin/packages/core/saved-objects/core-saved-objects-server-mocks/npm_module_types", "@types/kbn__core-saved-objects-utils-server": "link:bazel-bin/packages/core/saved-objects/core-saved-objects-utils-server/npm_module_types", "@types/kbn__core-server-internal-base": "link:bazel-bin/packages/core/server/internal-base/npm_module_types", + "@types/kbn__core-status-common": "link:bazel-bin/packages/core/status/core-status-common/npm_module_types", + "@types/kbn__core-status-common-internal": "link:bazel-bin/packages/core/status/core-status-common-internal/npm_module_types", + "@types/kbn__core-status-server": "link:bazel-bin/packages/core/status/core-status-server/npm_module_types", + "@types/kbn__core-status-server-internal": "link:bazel-bin/packages/core/status/core-status-server-internal/npm_module_types", + "@types/kbn__core-status-server-mocks": "link:bazel-bin/packages/core/status/core-status-server-mocks/npm_module_types", "@types/kbn__core-test-helpers-deprecations-getters": "link:bazel-bin/packages/core/test-helpers/core-test-helpers-deprecations-getters/npm_module_types", "@types/kbn__core-test-helpers-http-setup-browser": "link:bazel-bin/packages/core/test-helpers/core-test-helpers-http-setup-browser/npm_module_types", "@types/kbn__core-theme-browser": "link:bazel-bin/packages/core/theme/core-theme-browser/npm_module_types", @@ -1001,9 +1009,7 @@ "@types/kbn__interpreter": "link:bazel-bin/packages/kbn-interpreter/npm_module_types", "@types/kbn__io-ts-utils": "link:bazel-bin/packages/kbn-io-ts-utils/npm_module_types", "@types/kbn__jest-serializers": "link:bazel-bin/packages/kbn-jest-serializers/npm_module_types", - "@types/kbn__jsonc": "link:bazel-bin/packages/kbn-jsonc/npm_module_types", "@types/kbn__kbn-ci-stats-performance-metrics": "link:bazel-bin/packages/kbn-kbn-ci-stats-performance-metrics/npm_module_types", - "@types/kbn__kibana-manifest-parser": "link:bazel-bin/packages/kbn-kibana-manifest-parser/npm_module_types", "@types/kbn__kibana-manifest-schema": "link:bazel-bin/packages/kbn-kibana-manifest-schema/npm_module_types", "@types/kbn__logging": "link:bazel-bin/packages/kbn-logging/npm_module_types", "@types/kbn__logging-mocks": "link:bazel-bin/packages/kbn-logging-mocks/npm_module_types", diff --git a/packages/BUILD.bazel b/packages/BUILD.bazel index b5bd2f384d76bd..b898faee5fb07e 100644 --- a/packages/BUILD.bazel +++ b/packages/BUILD.bazel @@ -135,6 +135,11 @@ filegroup( "//packages/core/saved-objects/core-saved-objects-server-internal:build", "//packages/core/saved-objects/core-saved-objects-server-mocks:build", "//packages/core/saved-objects/core-saved-objects-utils-server:build", + "//packages/core/status/core-status-common:build", + "//packages/core/status/core-status-common-internal:build", + "//packages/core/status/core-status-server:build", + "//packages/core/status/core-status-server-internal:build", + "//packages/core/status/core-status-server-mocks:build", "//packages/core/test-helpers/core-test-helpers-deprecations-getters:build", "//packages/core/test-helpers/core-test-helpers-http-setup-browser:build", "//packages/core/theme/core-theme-browser:build", @@ -205,8 +210,6 @@ filegroup( "//packages/kbn-interpreter:build", "//packages/kbn-io-ts-utils:build", "//packages/kbn-jest-serializers:build", - "//packages/kbn-jsonc:build", - "//packages/kbn-kibana-manifest-parser:build", "//packages/kbn-kibana-manifest-schema:build", "//packages/kbn-logging:build", "//packages/kbn-logging-mocks:build", @@ -440,6 +443,11 @@ filegroup( "//packages/core/saved-objects/core-saved-objects-server-internal:build_types", "//packages/core/saved-objects/core-saved-objects-server-mocks:build_types", "//packages/core/saved-objects/core-saved-objects-utils-server:build_types", + "//packages/core/status/core-status-common:build_types", + "//packages/core/status/core-status-common-internal:build_types", + "//packages/core/status/core-status-server:build_types", + "//packages/core/status/core-status-server-internal:build_types", + "//packages/core/status/core-status-server-mocks:build_types", "//packages/core/test-helpers/core-test-helpers-deprecations-getters:build_types", "//packages/core/test-helpers/core-test-helpers-http-setup-browser:build_types", "//packages/core/theme/core-theme-browser:build_types", @@ -500,8 +508,6 @@ filegroup( "//packages/kbn-interpreter:build_types", "//packages/kbn-io-ts-utils:build_types", "//packages/kbn-jest-serializers:build_types", - "//packages/kbn-jsonc:build_types", - "//packages/kbn-kibana-manifest-parser:build_types", "//packages/kbn-kibana-manifest-schema:build_types", "//packages/kbn-logging:build_types", "//packages/kbn-logging-mocks:build_types", diff --git a/packages/analytics/client/kibana.jsonc b/packages/analytics/client/kibana.jsonc new file mode 100644 index 00000000000000..5f5aa11feb9942 --- /dev/null +++ b/packages/analytics/client/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/analytics-client", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/analytics/shippers/elastic_v3/browser/kibana.jsonc b/packages/analytics/shippers/elastic_v3/browser/kibana.jsonc new file mode 100644 index 00000000000000..cefab4152c994a --- /dev/null +++ b/packages/analytics/shippers/elastic_v3/browser/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/analytics-shippers-elastic-v3-browser", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/analytics/shippers/elastic_v3/common/kibana.jsonc b/packages/analytics/shippers/elastic_v3/common/kibana.jsonc new file mode 100644 index 00000000000000..c347233693ff3c --- /dev/null +++ b/packages/analytics/shippers/elastic_v3/common/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/analytics-shippers-elastic-v3-common", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/analytics/shippers/elastic_v3/server/kibana.jsonc b/packages/analytics/shippers/elastic_v3/server/kibana.jsonc new file mode 100644 index 00000000000000..11c29924f3c219 --- /dev/null +++ b/packages/analytics/shippers/elastic_v3/server/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/analytics-shippers-elastic-v3-server", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/analytics/shippers/fullstory/kibana.jsonc b/packages/analytics/shippers/fullstory/kibana.jsonc new file mode 100644 index 00000000000000..5d8720fa7486c7 --- /dev/null +++ b/packages/analytics/shippers/fullstory/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/analytics-shippers-fullstory", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/analytics/core-analytics-browser-internal/kibana.jsonc b/packages/core/analytics/core-analytics-browser-internal/kibana.jsonc new file mode 100644 index 00000000000000..45bd5d5bc041ac --- /dev/null +++ b/packages/core/analytics/core-analytics-browser-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-analytics-browser-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/analytics/core-analytics-browser-mocks/kibana.jsonc b/packages/core/analytics/core-analytics-browser-mocks/kibana.jsonc new file mode 100644 index 00000000000000..2c3ce58f95d624 --- /dev/null +++ b/packages/core/analytics/core-analytics-browser-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-analytics-browser-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/analytics/core-analytics-browser/kibana.jsonc b/packages/core/analytics/core-analytics-browser/kibana.jsonc new file mode 100644 index 00000000000000..a17a1e5d5e94bf --- /dev/null +++ b/packages/core/analytics/core-analytics-browser/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-analytics-browser", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/analytics/core-analytics-server-internal/kibana.jsonc b/packages/core/analytics/core-analytics-server-internal/kibana.jsonc new file mode 100644 index 00000000000000..1ae2d06e0fa774 --- /dev/null +++ b/packages/core/analytics/core-analytics-server-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-analytics-server-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/analytics/core-analytics-server-mocks/kibana.jsonc b/packages/core/analytics/core-analytics-server-mocks/kibana.jsonc new file mode 100644 index 00000000000000..9c49235144c4da --- /dev/null +++ b/packages/core/analytics/core-analytics-server-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-analytics-server-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/analytics/core-analytics-server/kibana.jsonc b/packages/core/analytics/core-analytics-server/kibana.jsonc new file mode 100644 index 00000000000000..d8faa138efc72a --- /dev/null +++ b/packages/core/analytics/core-analytics-server/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-analytics-server", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/application/core-application-browser-internal/kibana.jsonc b/packages/core/application/core-application-browser-internal/kibana.jsonc new file mode 100644 index 00000000000000..5ebb9290df1181 --- /dev/null +++ b/packages/core/application/core-application-browser-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-application-browser-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/application/core-application-browser-mocks/kibana.jsonc b/packages/core/application/core-application-browser-mocks/kibana.jsonc new file mode 100644 index 00000000000000..bdbeafdcc26529 --- /dev/null +++ b/packages/core/application/core-application-browser-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-application-browser-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/application/core-application-browser/kibana.jsonc b/packages/core/application/core-application-browser/kibana.jsonc new file mode 100644 index 00000000000000..6a8931fa36f745 --- /dev/null +++ b/packages/core/application/core-application-browser/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-application-browser", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/application/core-application-common/kibana.jsonc b/packages/core/application/core-application-common/kibana.jsonc new file mode 100644 index 00000000000000..da1cc4d8f7d9b8 --- /dev/null +++ b/packages/core/application/core-application-common/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-application-common", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/base/core-base-browser-internal/kibana.jsonc b/packages/core/base/core-base-browser-internal/kibana.jsonc new file mode 100644 index 00000000000000..7254343b42c5ff --- /dev/null +++ b/packages/core/base/core-base-browser-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-base-browser-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/base/core-base-browser-mocks/kibana.jsonc b/packages/core/base/core-base-browser-mocks/kibana.jsonc new file mode 100644 index 00000000000000..5911ba33ca9d40 --- /dev/null +++ b/packages/core/base/core-base-browser-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-base-browser-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/base/core-base-common-internal/kibana.jsonc b/packages/core/base/core-base-common-internal/kibana.jsonc new file mode 100644 index 00000000000000..61abd6d9a872cf --- /dev/null +++ b/packages/core/base/core-base-common-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-base-common-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/base/core-base-common/index.ts b/packages/core/base/core-base-common/index.ts index b2bbc96bc6a001..d2f7daafb3341f 100644 --- a/packages/core/base/core-base-common/index.ts +++ b/packages/core/base/core-base-common/index.ts @@ -9,5 +9,3 @@ export type { PluginOpaqueId, PluginName, DiscoveredPlugin } from './src/plugins'; export { PluginType } from './src/plugins'; export { EUI_STYLES_GLOBAL } from './src/eui'; -export { ServiceStatusLevels } from './src/service_status'; -export type { ServiceStatus, ServiceStatusLevel } from './src/service_status'; diff --git a/packages/core/base/core-base-common/kibana.jsonc b/packages/core/base/core-base-common/kibana.jsonc new file mode 100644 index 00000000000000..d72d5da919f1cb --- /dev/null +++ b/packages/core/base/core-base-common/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-base-common", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/base/core-base-server-internal/kibana.jsonc b/packages/core/base/core-base-server-internal/kibana.jsonc new file mode 100644 index 00000000000000..0a21a2b7e6384c --- /dev/null +++ b/packages/core/base/core-base-server-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-base-server-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/base/core-base-server-mocks/kibana.jsonc b/packages/core/base/core-base-server-mocks/kibana.jsonc new file mode 100644 index 00000000000000..762615e557b81c --- /dev/null +++ b/packages/core/base/core-base-server-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-base-server-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/capabilities/core-capabilities-browser-internal/kibana.jsonc b/packages/core/capabilities/core-capabilities-browser-internal/kibana.jsonc new file mode 100644 index 00000000000000..48f55a81a7a689 --- /dev/null +++ b/packages/core/capabilities/core-capabilities-browser-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-capabilities-browser-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/capabilities/core-capabilities-browser-mocks/kibana.jsonc b/packages/core/capabilities/core-capabilities-browser-mocks/kibana.jsonc new file mode 100644 index 00000000000000..5e6ddff3a4283d --- /dev/null +++ b/packages/core/capabilities/core-capabilities-browser-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-capabilities-browser-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/capabilities/core-capabilities-common/kibana.jsonc b/packages/core/capabilities/core-capabilities-common/kibana.jsonc new file mode 100644 index 00000000000000..5349e81ad36268 --- /dev/null +++ b/packages/core/capabilities/core-capabilities-common/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-capabilities-common", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/capabilities/core-capabilities-server-internal/kibana.jsonc b/packages/core/capabilities/core-capabilities-server-internal/kibana.jsonc new file mode 100644 index 00000000000000..3c464af07ea435 --- /dev/null +++ b/packages/core/capabilities/core-capabilities-server-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-capabilities-server-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/capabilities/core-capabilities-server-mocks/kibana.jsonc b/packages/core/capabilities/core-capabilities-server-mocks/kibana.jsonc new file mode 100644 index 00000000000000..5404ed714a6eb5 --- /dev/null +++ b/packages/core/capabilities/core-capabilities-server-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-capabilities-server-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/capabilities/core-capabilities-server/kibana.jsonc b/packages/core/capabilities/core-capabilities-server/kibana.jsonc new file mode 100644 index 00000000000000..dc6e6ac3c1279b --- /dev/null +++ b/packages/core/capabilities/core-capabilities-server/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-capabilities-server", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/chrome/core-chrome-browser-internal/kibana.jsonc b/packages/core/chrome/core-chrome-browser-internal/kibana.jsonc new file mode 100644 index 00000000000000..2d0a7bada7bb92 --- /dev/null +++ b/packages/core/chrome/core-chrome-browser-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-chrome-browser-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/chrome/core-chrome-browser-mocks/kibana.jsonc b/packages/core/chrome/core-chrome-browser-mocks/kibana.jsonc new file mode 100644 index 00000000000000..5968ce1224da8e --- /dev/null +++ b/packages/core/chrome/core-chrome-browser-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-chrome-browser-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/chrome/core-chrome-browser/kibana.jsonc b/packages/core/chrome/core-chrome-browser/kibana.jsonc new file mode 100644 index 00000000000000..64eba064445078 --- /dev/null +++ b/packages/core/chrome/core-chrome-browser/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-chrome-browser", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/config/core-config-server-internal/kibana.jsonc b/packages/core/config/core-config-server-internal/kibana.jsonc new file mode 100644 index 00000000000000..a6ba80afe95909 --- /dev/null +++ b/packages/core/config/core-config-server-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-config-server-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/deprecations/core-deprecations-browser-internal/kibana.jsonc b/packages/core/deprecations/core-deprecations-browser-internal/kibana.jsonc new file mode 100644 index 00000000000000..c5bf07aa7052f5 --- /dev/null +++ b/packages/core/deprecations/core-deprecations-browser-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-deprecations-browser-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/deprecations/core-deprecations-browser-mocks/kibana.jsonc b/packages/core/deprecations/core-deprecations-browser-mocks/kibana.jsonc new file mode 100644 index 00000000000000..28424208cd582c --- /dev/null +++ b/packages/core/deprecations/core-deprecations-browser-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-deprecations-browser-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/deprecations/core-deprecations-browser/kibana.jsonc b/packages/core/deprecations/core-deprecations-browser/kibana.jsonc new file mode 100644 index 00000000000000..3e708f34935b58 --- /dev/null +++ b/packages/core/deprecations/core-deprecations-browser/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-deprecations-browser", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/deprecations/core-deprecations-common/kibana.jsonc b/packages/core/deprecations/core-deprecations-common/kibana.jsonc new file mode 100644 index 00000000000000..60494dec2502f0 --- /dev/null +++ b/packages/core/deprecations/core-deprecations-common/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-deprecations-common", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/deprecations/core-deprecations-server-internal/kibana.jsonc b/packages/core/deprecations/core-deprecations-server-internal/kibana.jsonc new file mode 100644 index 00000000000000..367adb98a89b2d --- /dev/null +++ b/packages/core/deprecations/core-deprecations-server-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-deprecations-server-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/deprecations/core-deprecations-server-mocks/kibana.jsonc b/packages/core/deprecations/core-deprecations-server-mocks/kibana.jsonc new file mode 100644 index 00000000000000..fc56bc34368f1d --- /dev/null +++ b/packages/core/deprecations/core-deprecations-server-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-deprecations-server-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/deprecations/core-deprecations-server/kibana.jsonc b/packages/core/deprecations/core-deprecations-server/kibana.jsonc new file mode 100644 index 00000000000000..96270007d4ad34 --- /dev/null +++ b/packages/core/deprecations/core-deprecations-server/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-deprecations-server", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/doc-links/core-doc-links-browser-internal/kibana.jsonc b/packages/core/doc-links/core-doc-links-browser-internal/kibana.jsonc new file mode 100644 index 00000000000000..b72ad3a17021a3 --- /dev/null +++ b/packages/core/doc-links/core-doc-links-browser-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-doc-links-browser-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/doc-links/core-doc-links-browser-mocks/kibana.jsonc b/packages/core/doc-links/core-doc-links-browser-mocks/kibana.jsonc new file mode 100644 index 00000000000000..d1c5b7af28390b --- /dev/null +++ b/packages/core/doc-links/core-doc-links-browser-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-doc-links-browser-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/doc-links/core-doc-links-browser/kibana.jsonc b/packages/core/doc-links/core-doc-links-browser/kibana.jsonc new file mode 100644 index 00000000000000..68ed9f30aff6b8 --- /dev/null +++ b/packages/core/doc-links/core-doc-links-browser/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-doc-links-browser", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/doc-links/core-doc-links-server-internal/kibana.jsonc b/packages/core/doc-links/core-doc-links-server-internal/kibana.jsonc new file mode 100644 index 00000000000000..f2158ec018209b --- /dev/null +++ b/packages/core/doc-links/core-doc-links-server-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-doc-links-server-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/doc-links/core-doc-links-server-mocks/kibana.jsonc b/packages/core/doc-links/core-doc-links-server-mocks/kibana.jsonc new file mode 100644 index 00000000000000..5d61cf066d3125 --- /dev/null +++ b/packages/core/doc-links/core-doc-links-server-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-doc-links-server-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/doc-links/core-doc-links-server/kibana.jsonc b/packages/core/doc-links/core-doc-links-server/kibana.jsonc new file mode 100644 index 00000000000000..e0460f4da99bcd --- /dev/null +++ b/packages/core/doc-links/core-doc-links-server/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-doc-links-server", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/elasticsearch/core-elasticsearch-client-server-internal/kibana.jsonc b/packages/core/elasticsearch/core-elasticsearch-client-server-internal/kibana.jsonc new file mode 100644 index 00000000000000..e2393e888d5de0 --- /dev/null +++ b/packages/core/elasticsearch/core-elasticsearch-client-server-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-elasticsearch-client-server-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/elasticsearch/core-elasticsearch-client-server-mocks/kibana.jsonc b/packages/core/elasticsearch/core-elasticsearch-client-server-mocks/kibana.jsonc new file mode 100644 index 00000000000000..ae267b45ddc1cd --- /dev/null +++ b/packages/core/elasticsearch/core-elasticsearch-client-server-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-elasticsearch-client-server-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/elasticsearch/core-elasticsearch-server-internal/BUILD.bazel b/packages/core/elasticsearch/core-elasticsearch-server-internal/BUILD.bazel index ab9738d8a6ca33..0609c66baced3a 100644 --- a/packages/core/elasticsearch/core-elasticsearch-server-internal/BUILD.bazel +++ b/packages/core/elasticsearch/core-elasticsearch-server-internal/BUILD.bazel @@ -70,6 +70,7 @@ TYPES_DEPS = [ "//packages/kbn-config-schema:npm_module_types", "//packages/core/base/core-base-common:npm_module_types", "//packages/core/base/core-base-server-internal:npm_module_types", + "//packages/core/status/core-status-common:npm_module_types", "//packages/core/analytics/core-analytics-server:npm_module_types", "//packages/core/http/core-http-server:npm_module_types", "//packages/core/http/core-http-server-internal:npm_module_types", diff --git a/packages/core/elasticsearch/core-elasticsearch-server-internal/kibana.jsonc b/packages/core/elasticsearch/core-elasticsearch-server-internal/kibana.jsonc new file mode 100644 index 00000000000000..34ea515ba045f5 --- /dev/null +++ b/packages/core/elasticsearch/core-elasticsearch-server-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-elasticsearch-server-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/elasticsearch/core-elasticsearch-server-internal/src/status.test.ts b/packages/core/elasticsearch/core-elasticsearch-server-internal/src/status.test.ts index f6aec43e680c40..8889125bf1d4ec 100644 --- a/packages/core/elasticsearch/core-elasticsearch-server-internal/src/status.test.ts +++ b/packages/core/elasticsearch/core-elasticsearch-server-internal/src/status.test.ts @@ -9,7 +9,7 @@ import { take } from 'rxjs/operators'; import { Subject, of } from 'rxjs'; -import { ServiceStatusLevels, ServiceStatusLevel, ServiceStatus } from '@kbn/core-base-common'; +import { ServiceStatusLevels, ServiceStatusLevel, ServiceStatus } from '@kbn/core-status-common'; import { calculateStatus$ } from './status'; import { NodesVersionCompatibility } from './version_check/ensure_es_version'; diff --git a/packages/core/elasticsearch/core-elasticsearch-server-internal/src/status.ts b/packages/core/elasticsearch/core-elasticsearch-server-internal/src/status.ts index 5a38f11432b7bf..fbb11824d8e83d 100644 --- a/packages/core/elasticsearch/core-elasticsearch-server-internal/src/status.ts +++ b/packages/core/elasticsearch/core-elasticsearch-server-internal/src/status.ts @@ -8,7 +8,7 @@ import { Observable, merge, of } from 'rxjs'; import { map } from 'rxjs/operators'; -import { ServiceStatus, ServiceStatusLevels } from '@kbn/core-base-common'; +import { ServiceStatus, ServiceStatusLevels } from '@kbn/core-status-common'; import { ElasticsearchStatusMeta } from './types'; import { NodesVersionCompatibility } from './version_check/ensure_es_version'; diff --git a/packages/core/elasticsearch/core-elasticsearch-server-internal/src/types.ts b/packages/core/elasticsearch/core-elasticsearch-server-internal/src/types.ts index 57f3620a7911d0..8d05ad0c4cd0ad 100644 --- a/packages/core/elasticsearch/core-elasticsearch-server-internal/src/types.ts +++ b/packages/core/elasticsearch/core-elasticsearch-server-internal/src/types.ts @@ -12,7 +12,7 @@ import type { ElasticsearchServiceStart, ElasticsearchServiceSetup, } from '@kbn/core-elasticsearch-server'; -import type { ServiceStatus } from '@kbn/core-base-common'; +import type { ServiceStatus } from '@kbn/core-status-common'; import type { NodesVersionCompatibility, NodeInfo } from './version_check/ensure_es_version'; import type { ClusterInfo } from './get_cluster_info'; diff --git a/packages/core/elasticsearch/core-elasticsearch-server-mocks/BUILD.bazel b/packages/core/elasticsearch/core-elasticsearch-server-mocks/BUILD.bazel index da292814321f76..41de319850636c 100644 --- a/packages/core/elasticsearch/core-elasticsearch-server-mocks/BUILD.bazel +++ b/packages/core/elasticsearch/core-elasticsearch-server-mocks/BUILD.bazel @@ -43,7 +43,7 @@ TYPES_DEPS = [ "@npm//@types/jest", "@npm//rxjs", "//packages/kbn-utility-types:npm_module_types", - "//packages/core/base/core-base-common:npm_module_types", + "//packages/core/status/core-status-common:npm_module_types", "//packages/core/elasticsearch/core-elasticsearch-server:npm_module_types", "//packages/core/elasticsearch/core-elasticsearch-client-server-mocks:npm_module_types", "//packages/core/elasticsearch/core-elasticsearch-server-internal:npm_module_types", diff --git a/packages/core/elasticsearch/core-elasticsearch-server-mocks/kibana.jsonc b/packages/core/elasticsearch/core-elasticsearch-server-mocks/kibana.jsonc new file mode 100644 index 00000000000000..d08d5d04cbb39b --- /dev/null +++ b/packages/core/elasticsearch/core-elasticsearch-server-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-elasticsearch-server-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/elasticsearch/core-elasticsearch-server-mocks/src/elasticsearch_service.mock.ts b/packages/core/elasticsearch/core-elasticsearch-server-mocks/src/elasticsearch_service.mock.ts index d3a5bfe5e96452..a1323be0ea71b5 100644 --- a/packages/core/elasticsearch/core-elasticsearch-server-mocks/src/elasticsearch_service.mock.ts +++ b/packages/core/elasticsearch/core-elasticsearch-server-mocks/src/elasticsearch_service.mock.ts @@ -27,7 +27,7 @@ import type { NodesVersionCompatibility, ClusterInfo, } from '@kbn/core-elasticsearch-server-internal'; -import { type ServiceStatus, ServiceStatusLevels } from '@kbn/core-base-common'; +import { type ServiceStatus, ServiceStatusLevels } from '@kbn/core-status-common'; type MockedElasticSearchServicePreboot = jest.Mocked; diff --git a/packages/core/elasticsearch/core-elasticsearch-server/kibana.jsonc b/packages/core/elasticsearch/core-elasticsearch-server/kibana.jsonc new file mode 100644 index 00000000000000..5bf72319cc41b4 --- /dev/null +++ b/packages/core/elasticsearch/core-elasticsearch-server/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-elasticsearch-server", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/environment/core-environment-server-internal/kibana.jsonc b/packages/core/environment/core-environment-server-internal/kibana.jsonc new file mode 100644 index 00000000000000..9d8de1124ce0f7 --- /dev/null +++ b/packages/core/environment/core-environment-server-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-environment-server-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/environment/core-environment-server-mocks/kibana.jsonc b/packages/core/environment/core-environment-server-mocks/kibana.jsonc new file mode 100644 index 00000000000000..6644816727a709 --- /dev/null +++ b/packages/core/environment/core-environment-server-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-environment-server-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/execution-context/core-execution-context-browser-internal/kibana.jsonc b/packages/core/execution-context/core-execution-context-browser-internal/kibana.jsonc new file mode 100644 index 00000000000000..1771d94a14b8a9 --- /dev/null +++ b/packages/core/execution-context/core-execution-context-browser-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-execution-context-browser-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/execution-context/core-execution-context-browser-mocks/kibana.jsonc b/packages/core/execution-context/core-execution-context-browser-mocks/kibana.jsonc new file mode 100644 index 00000000000000..8d27a9ec919dd6 --- /dev/null +++ b/packages/core/execution-context/core-execution-context-browser-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-execution-context-browser-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/execution-context/core-execution-context-browser/kibana.jsonc b/packages/core/execution-context/core-execution-context-browser/kibana.jsonc new file mode 100644 index 00000000000000..550d63fc67de1c --- /dev/null +++ b/packages/core/execution-context/core-execution-context-browser/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-execution-context-browser", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/execution-context/core-execution-context-common/kibana.jsonc b/packages/core/execution-context/core-execution-context-common/kibana.jsonc new file mode 100644 index 00000000000000..d3cf33be164d20 --- /dev/null +++ b/packages/core/execution-context/core-execution-context-common/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-execution-context-common", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/execution-context/core-execution-context-server-internal/kibana.jsonc b/packages/core/execution-context/core-execution-context-server-internal/kibana.jsonc new file mode 100644 index 00000000000000..d344f53f34f57c --- /dev/null +++ b/packages/core/execution-context/core-execution-context-server-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-execution-context-server-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/execution-context/core-execution-context-server-mocks/kibana.jsonc b/packages/core/execution-context/core-execution-context-server-mocks/kibana.jsonc new file mode 100644 index 00000000000000..e73d0b4f9b2169 --- /dev/null +++ b/packages/core/execution-context/core-execution-context-server-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-execution-context-server-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/execution-context/core-execution-context-server/kibana.jsonc b/packages/core/execution-context/core-execution-context-server/kibana.jsonc new file mode 100644 index 00000000000000..5de7baaaccb329 --- /dev/null +++ b/packages/core/execution-context/core-execution-context-server/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-execution-context-server", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/fatal-errors/core-fatal-errors-browser-internal/kibana.jsonc b/packages/core/fatal-errors/core-fatal-errors-browser-internal/kibana.jsonc new file mode 100644 index 00000000000000..76752593fd00c0 --- /dev/null +++ b/packages/core/fatal-errors/core-fatal-errors-browser-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-fatal-errors-browser-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/fatal-errors/core-fatal-errors-browser-mocks/kibana.jsonc b/packages/core/fatal-errors/core-fatal-errors-browser-mocks/kibana.jsonc new file mode 100644 index 00000000000000..6109111801eb18 --- /dev/null +++ b/packages/core/fatal-errors/core-fatal-errors-browser-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-fatal-errors-browser-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/fatal-errors/core-fatal-errors-browser/kibana.jsonc b/packages/core/fatal-errors/core-fatal-errors-browser/kibana.jsonc new file mode 100644 index 00000000000000..95423568bca937 --- /dev/null +++ b/packages/core/fatal-errors/core-fatal-errors-browser/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-fatal-errors-browser", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/http/core-http-browser-internal/kibana.jsonc b/packages/core/http/core-http-browser-internal/kibana.jsonc new file mode 100644 index 00000000000000..d5855d71ca1786 --- /dev/null +++ b/packages/core/http/core-http-browser-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-http-browser-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/http/core-http-browser-mocks/kibana.jsonc b/packages/core/http/core-http-browser-mocks/kibana.jsonc new file mode 100644 index 00000000000000..9819977cb419d7 --- /dev/null +++ b/packages/core/http/core-http-browser-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-http-browser-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/http/core-http-browser/kibana.jsonc b/packages/core/http/core-http-browser/kibana.jsonc new file mode 100644 index 00000000000000..87510d65336e3e --- /dev/null +++ b/packages/core/http/core-http-browser/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-http-browser", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/http/core-http-common/kibana.jsonc b/packages/core/http/core-http-common/kibana.jsonc new file mode 100644 index 00000000000000..bdf00df353c638 --- /dev/null +++ b/packages/core/http/core-http-common/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-http-common", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/http/core-http-context-server-internal/kibana.jsonc b/packages/core/http/core-http-context-server-internal/kibana.jsonc new file mode 100644 index 00000000000000..18f306d7217593 --- /dev/null +++ b/packages/core/http/core-http-context-server-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-http-context-server-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/http/core-http-context-server-mocks/kibana.jsonc b/packages/core/http/core-http-context-server-mocks/kibana.jsonc new file mode 100644 index 00000000000000..323d78350596ba --- /dev/null +++ b/packages/core/http/core-http-context-server-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-http-context-server-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/http/core-http-router-server-internal/kibana.jsonc b/packages/core/http/core-http-router-server-internal/kibana.jsonc new file mode 100644 index 00000000000000..5f7482d9fa06cb --- /dev/null +++ b/packages/core/http/core-http-router-server-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-http-router-server-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/http/core-http-router-server-mocks/kibana.jsonc b/packages/core/http/core-http-router-server-mocks/kibana.jsonc new file mode 100644 index 00000000000000..a1883a9c92ff72 --- /dev/null +++ b/packages/core/http/core-http-router-server-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-http-router-server-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/http/core-http-server-internal/kibana.jsonc b/packages/core/http/core-http-server-internal/kibana.jsonc new file mode 100644 index 00000000000000..0d1d5b04eaae2b --- /dev/null +++ b/packages/core/http/core-http-server-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-http-server-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/http/core-http-server-mocks/kibana.jsonc b/packages/core/http/core-http-server-mocks/kibana.jsonc new file mode 100644 index 00000000000000..598898176f62c0 --- /dev/null +++ b/packages/core/http/core-http-server-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-http-server-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/http/core-http-server/kibana.jsonc b/packages/core/http/core-http-server/kibana.jsonc new file mode 100644 index 00000000000000..da671fec6aaec9 --- /dev/null +++ b/packages/core/http/core-http-server/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-http-server", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/i18n/core-i18n-browser-internal/kibana.jsonc b/packages/core/i18n/core-i18n-browser-internal/kibana.jsonc new file mode 100644 index 00000000000000..424e9d3dcdbcd3 --- /dev/null +++ b/packages/core/i18n/core-i18n-browser-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-i18n-browser-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/i18n/core-i18n-browser-mocks/kibana.jsonc b/packages/core/i18n/core-i18n-browser-mocks/kibana.jsonc new file mode 100644 index 00000000000000..0f5b73ed3b4537 --- /dev/null +++ b/packages/core/i18n/core-i18n-browser-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-i18n-browser-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/i18n/core-i18n-browser/kibana.jsonc b/packages/core/i18n/core-i18n-browser/kibana.jsonc new file mode 100644 index 00000000000000..dcbf951b201f10 --- /dev/null +++ b/packages/core/i18n/core-i18n-browser/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-i18n-browser", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/i18n/core-i18n-server-internal/kibana.jsonc b/packages/core/i18n/core-i18n-server-internal/kibana.jsonc new file mode 100644 index 00000000000000..3b89a42976bbcd --- /dev/null +++ b/packages/core/i18n/core-i18n-server-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-i18n-server-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/i18n/core-i18n-server-mocks/kibana.jsonc b/packages/core/i18n/core-i18n-server-mocks/kibana.jsonc new file mode 100644 index 00000000000000..41ef001641b579 --- /dev/null +++ b/packages/core/i18n/core-i18n-server-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-i18n-server-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/i18n/core-i18n-server/kibana.jsonc b/packages/core/i18n/core-i18n-server/kibana.jsonc new file mode 100644 index 00000000000000..c32d5d9cd8e7b8 --- /dev/null +++ b/packages/core/i18n/core-i18n-server/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-i18n-server", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/injected-metadata/core-injected-metadata-browser-internal/kibana.jsonc b/packages/core/injected-metadata/core-injected-metadata-browser-internal/kibana.jsonc new file mode 100644 index 00000000000000..d66f834c08eb36 --- /dev/null +++ b/packages/core/injected-metadata/core-injected-metadata-browser-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-injected-metadata-browser-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/injected-metadata/core-injected-metadata-browser-mocks/kibana.jsonc b/packages/core/injected-metadata/core-injected-metadata-browser-mocks/kibana.jsonc new file mode 100644 index 00000000000000..cfbfae1b907e21 --- /dev/null +++ b/packages/core/injected-metadata/core-injected-metadata-browser-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-injected-metadata-browser-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/injected-metadata/core-injected-metadata-browser/kibana.jsonc b/packages/core/injected-metadata/core-injected-metadata-browser/kibana.jsonc new file mode 100644 index 00000000000000..d10647084cd47e --- /dev/null +++ b/packages/core/injected-metadata/core-injected-metadata-browser/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-injected-metadata-browser", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/injected-metadata/core-injected-metadata-common-internal/kibana.jsonc b/packages/core/injected-metadata/core-injected-metadata-common-internal/kibana.jsonc new file mode 100644 index 00000000000000..88943c788515f5 --- /dev/null +++ b/packages/core/injected-metadata/core-injected-metadata-common-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-injected-metadata-common-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/integrations/core-integrations-browser-internal/kibana.jsonc b/packages/core/integrations/core-integrations-browser-internal/kibana.jsonc new file mode 100644 index 00000000000000..fd72743c085976 --- /dev/null +++ b/packages/core/integrations/core-integrations-browser-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-integrations-browser-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/integrations/core-integrations-browser-mocks/kibana.jsonc b/packages/core/integrations/core-integrations-browser-mocks/kibana.jsonc new file mode 100644 index 00000000000000..a4bcddaecba14b --- /dev/null +++ b/packages/core/integrations/core-integrations-browser-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-integrations-browser-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/logging/core-logging-server-internal/kibana.jsonc b/packages/core/logging/core-logging-server-internal/kibana.jsonc new file mode 100644 index 00000000000000..ec5ab06a6effdb --- /dev/null +++ b/packages/core/logging/core-logging-server-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-logging-server-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/logging/core-logging-server-mocks/kibana.jsonc b/packages/core/logging/core-logging-server-mocks/kibana.jsonc new file mode 100644 index 00000000000000..83793b02fca6be --- /dev/null +++ b/packages/core/logging/core-logging-server-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-logging-server-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/logging/core-logging-server/kibana.jsonc b/packages/core/logging/core-logging-server/kibana.jsonc new file mode 100644 index 00000000000000..27dadd782dcdcb --- /dev/null +++ b/packages/core/logging/core-logging-server/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-logging-server", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/metrics/core-metrics-collectors-server-internal/kibana.jsonc b/packages/core/metrics/core-metrics-collectors-server-internal/kibana.jsonc new file mode 100644 index 00000000000000..39a1aff44dba52 --- /dev/null +++ b/packages/core/metrics/core-metrics-collectors-server-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-metrics-collectors-server-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/metrics/core-metrics-collectors-server-mocks/kibana.jsonc b/packages/core/metrics/core-metrics-collectors-server-mocks/kibana.jsonc new file mode 100644 index 00000000000000..053d67afb5f687 --- /dev/null +++ b/packages/core/metrics/core-metrics-collectors-server-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-metrics-collectors-server-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/metrics/core-metrics-server-internal/kibana.jsonc b/packages/core/metrics/core-metrics-server-internal/kibana.jsonc new file mode 100644 index 00000000000000..325f7e64bbb520 --- /dev/null +++ b/packages/core/metrics/core-metrics-server-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-metrics-server-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/metrics/core-metrics-server-mocks/kibana.jsonc b/packages/core/metrics/core-metrics-server-mocks/kibana.jsonc new file mode 100644 index 00000000000000..6af29213a86ce5 --- /dev/null +++ b/packages/core/metrics/core-metrics-server-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-metrics-server-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/metrics/core-metrics-server/kibana.jsonc b/packages/core/metrics/core-metrics-server/kibana.jsonc new file mode 100644 index 00000000000000..64136f9466cb7c --- /dev/null +++ b/packages/core/metrics/core-metrics-server/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-metrics-server", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/mount-utils/core-mount-utils-browser-internal/kibana.jsonc b/packages/core/mount-utils/core-mount-utils-browser-internal/kibana.jsonc new file mode 100644 index 00000000000000..c0853a96b395ad --- /dev/null +++ b/packages/core/mount-utils/core-mount-utils-browser-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-mount-utils-browser-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/mount-utils/core-mount-utils-browser/kibana.jsonc b/packages/core/mount-utils/core-mount-utils-browser/kibana.jsonc new file mode 100644 index 00000000000000..8f8977af53327b --- /dev/null +++ b/packages/core/mount-utils/core-mount-utils-browser/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-mount-utils-browser", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/node/core-node-server-internal/kibana.jsonc b/packages/core/node/core-node-server-internal/kibana.jsonc new file mode 100644 index 00000000000000..dedee6005b4838 --- /dev/null +++ b/packages/core/node/core-node-server-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-node-server-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/node/core-node-server-mocks/kibana.jsonc b/packages/core/node/core-node-server-mocks/kibana.jsonc new file mode 100644 index 00000000000000..7070f0218b1c93 --- /dev/null +++ b/packages/core/node/core-node-server-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-node-server-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/node/core-node-server/kibana.jsonc b/packages/core/node/core-node-server/kibana.jsonc new file mode 100644 index 00000000000000..a2322cffe8ac4f --- /dev/null +++ b/packages/core/node/core-node-server/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-node-server", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/notifications/core-notifications-browser-internal/kibana.jsonc b/packages/core/notifications/core-notifications-browser-internal/kibana.jsonc new file mode 100644 index 00000000000000..03ad251d65c7bc --- /dev/null +++ b/packages/core/notifications/core-notifications-browser-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-notifications-browser-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/notifications/core-notifications-browser-mocks/kibana.jsonc b/packages/core/notifications/core-notifications-browser-mocks/kibana.jsonc new file mode 100644 index 00000000000000..d1c1d8f58f935c --- /dev/null +++ b/packages/core/notifications/core-notifications-browser-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-notifications-browser-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/notifications/core-notifications-browser/kibana.jsonc b/packages/core/notifications/core-notifications-browser/kibana.jsonc new file mode 100644 index 00000000000000..ae6140a86a2005 --- /dev/null +++ b/packages/core/notifications/core-notifications-browser/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-notifications-browser", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/overlays/core-overlays-browser-internal/kibana.jsonc b/packages/core/overlays/core-overlays-browser-internal/kibana.jsonc new file mode 100644 index 00000000000000..8890a3c132d666 --- /dev/null +++ b/packages/core/overlays/core-overlays-browser-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-overlays-browser-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/overlays/core-overlays-browser-mocks/kibana.jsonc b/packages/core/overlays/core-overlays-browser-mocks/kibana.jsonc new file mode 100644 index 00000000000000..61b14d5cbc8b0d --- /dev/null +++ b/packages/core/overlays/core-overlays-browser-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-overlays-browser-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/overlays/core-overlays-browser/kibana.jsonc b/packages/core/overlays/core-overlays-browser/kibana.jsonc new file mode 100644 index 00000000000000..de43c7689f1fc7 --- /dev/null +++ b/packages/core/overlays/core-overlays-browser/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-overlays-browser", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/preboot/core-preboot-server-internal/kibana.jsonc b/packages/core/preboot/core-preboot-server-internal/kibana.jsonc new file mode 100644 index 00000000000000..9a2eadb716ea82 --- /dev/null +++ b/packages/core/preboot/core-preboot-server-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-preboot-server-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/preboot/core-preboot-server-mocks/kibana.jsonc b/packages/core/preboot/core-preboot-server-mocks/kibana.jsonc new file mode 100644 index 00000000000000..87a035b99530e2 --- /dev/null +++ b/packages/core/preboot/core-preboot-server-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-preboot-server-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/preboot/core-preboot-server/kibana.jsonc b/packages/core/preboot/core-preboot-server/kibana.jsonc new file mode 100644 index 00000000000000..e529cfdd656852 --- /dev/null +++ b/packages/core/preboot/core-preboot-server/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-preboot-server", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/rendering/core-rendering-browser-internal/kibana.jsonc b/packages/core/rendering/core-rendering-browser-internal/kibana.jsonc new file mode 100644 index 00000000000000..aaca72f8b4843b --- /dev/null +++ b/packages/core/rendering/core-rendering-browser-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-rendering-browser-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/rendering/core-rendering-browser-mocks/kibana.jsonc b/packages/core/rendering/core-rendering-browser-mocks/kibana.jsonc new file mode 100644 index 00000000000000..82b891ad721d30 --- /dev/null +++ b/packages/core/rendering/core-rendering-browser-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-rendering-browser-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/saved-objects/core-saved-objects-api-browser/kibana.jsonc b/packages/core/saved-objects/core-saved-objects-api-browser/kibana.jsonc new file mode 100644 index 00000000000000..dc9bc275a4cb14 --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-api-browser/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-saved-objects-api-browser", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/saved-objects/core-saved-objects-api-server-internal/kibana.jsonc b/packages/core/saved-objects/core-saved-objects-api-server-internal/kibana.jsonc new file mode 100644 index 00000000000000..afef1f03740a08 --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-api-server-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-saved-objects-api-server-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/saved-objects/core-saved-objects-api-server-mocks/kibana.jsonc b/packages/core/saved-objects/core-saved-objects-api-server-mocks/kibana.jsonc new file mode 100644 index 00000000000000..beb632af28c088 --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-api-server-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-saved-objects-api-server-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/saved-objects/core-saved-objects-api-server/kibana.jsonc b/packages/core/saved-objects/core-saved-objects-api-server/kibana.jsonc new file mode 100644 index 00000000000000..08ebe81051b657 --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-api-server/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-saved-objects-api-server", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/saved-objects/core-saved-objects-base-server-internal/kibana.jsonc b/packages/core/saved-objects/core-saved-objects-base-server-internal/kibana.jsonc new file mode 100644 index 00000000000000..a14d74263ec95f --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-base-server-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-saved-objects-base-server-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/saved-objects/core-saved-objects-base-server-mocks/kibana.jsonc b/packages/core/saved-objects/core-saved-objects-base-server-mocks/kibana.jsonc new file mode 100644 index 00000000000000..deab59887d747a --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-base-server-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-saved-objects-base-server-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/saved-objects/core-saved-objects-browser-internal/kibana.jsonc b/packages/core/saved-objects/core-saved-objects-browser-internal/kibana.jsonc new file mode 100644 index 00000000000000..ec1e45b0ffb38b --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-browser-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-saved-objects-browser-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/saved-objects/core-saved-objects-browser-mocks/kibana.jsonc b/packages/core/saved-objects/core-saved-objects-browser-mocks/kibana.jsonc new file mode 100644 index 00000000000000..cf0623a36b7089 --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-browser-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-saved-objects-browser-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/saved-objects/core-saved-objects-browser/kibana.jsonc b/packages/core/saved-objects/core-saved-objects-browser/kibana.jsonc new file mode 100644 index 00000000000000..923add888b03e0 --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-browser/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-saved-objects-browser", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/saved-objects/core-saved-objects-common/kibana.jsonc b/packages/core/saved-objects/core-saved-objects-common/kibana.jsonc new file mode 100644 index 00000000000000..d82a9bf67d3235 --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-common/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-saved-objects-common", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/saved-objects/core-saved-objects-import-export-server-internal/kibana.jsonc b/packages/core/saved-objects/core-saved-objects-import-export-server-internal/kibana.jsonc new file mode 100644 index 00000000000000..eabb9e670baf32 --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-import-export-server-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-saved-objects-import-export-server-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/saved-objects/core-saved-objects-import-export-server-mocks/kibana.jsonc b/packages/core/saved-objects/core-saved-objects-import-export-server-mocks/kibana.jsonc new file mode 100644 index 00000000000000..174960bd1aadcd --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-import-export-server-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-saved-objects-import-export-server-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/kibana.jsonc b/packages/core/saved-objects/core-saved-objects-migration-server-internal/kibana.jsonc new file mode 100644 index 00000000000000..4a04817a139c2c --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-saved-objects-migration-server-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-mocks/kibana.jsonc b/packages/core/saved-objects/core-saved-objects-migration-server-mocks/kibana.jsonc new file mode 100644 index 00000000000000..b27f6951cb0d07 --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-migration-server-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-saved-objects-migration-server-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/saved-objects/core-saved-objects-server-internal/BUILD.bazel b/packages/core/saved-objects/core-saved-objects-server-internal/BUILD.bazel index 5c5474ce0737a9..d071fd819314d1 100644 --- a/packages/core/saved-objects/core-saved-objects-server-internal/BUILD.bazel +++ b/packages/core/saved-objects/core-saved-objects-server-internal/BUILD.bazel @@ -39,6 +39,7 @@ RUNTIME_DEPS = [ "@npm//json-stable-stringify", "//packages/kbn-config-schema", "//packages/core/base/core-base-common", + "//packages/core/status/core-status-common", "//packages/core/saved-objects/core-saved-objects-base-server-internal", "//packages/core/saved-objects/core-saved-objects-api-server-internal", "//packages/core/saved-objects/core-saved-objects-migration-server-internal", @@ -52,6 +53,7 @@ TYPES_DEPS = [ "//packages/kbn-config-schema:npm_module_types", "//packages/kbn-logging:npm_module_types", "//packages/core/base/core-base-common:npm_module_types", + "//packages/core/status/core-status-common:npm_module_types", "//packages/core/deprecations/core-deprecations-common:npm_module_types", "//packages/core/http/core-http-server:npm_module_types", "//packages/core/http/core-http-server-internal:npm_module_types", diff --git a/packages/core/saved-objects/core-saved-objects-server-internal/kibana.jsonc b/packages/core/saved-objects/core-saved-objects-server-internal/kibana.jsonc new file mode 100644 index 00000000000000..43cadd207f9145 --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-server-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-saved-objects-server-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/saved-objects/core-saved-objects-server-internal/src/saved_objects_service.ts b/packages/core/saved-objects/core-saved-objects-server-internal/src/saved_objects_service.ts index c158bb758f6244..8036a997d0d516 100644 --- a/packages/core/saved-objects/core-saved-objects-server-internal/src/saved_objects_service.ts +++ b/packages/core/saved-objects/core-saved-objects-server-internal/src/saved_objects_service.ts @@ -9,7 +9,7 @@ import { Subject, Observable, firstValueFrom } from 'rxjs'; import { filter, take, switchMap } from 'rxjs/operators'; import type { Logger } from '@kbn/logging'; -import type { ServiceStatus } from '@kbn/core-base-common'; +import type { ServiceStatus } from '@kbn/core-status-common'; import type { CoreContext, CoreService } from '@kbn/core-base-server-internal'; import type { DocLinksServiceStart } from '@kbn/core-doc-links-server'; import type { KibanaRequest } from '@kbn/core-http-server'; diff --git a/packages/core/saved-objects/core-saved-objects-server-internal/src/status.test.ts b/packages/core/saved-objects/core-saved-objects-server-internal/src/status.test.ts index 3565ab406feb38..a6c07ee6ea1ba9 100644 --- a/packages/core/saved-objects/core-saved-objects-server-internal/src/status.test.ts +++ b/packages/core/saved-objects/core-saved-objects-server-internal/src/status.test.ts @@ -7,7 +7,7 @@ */ import { of, Observable } from 'rxjs'; -import { type ServiceStatus, ServiceStatusLevels } from '@kbn/core-base-common'; +import { type ServiceStatus, ServiceStatusLevels } from '@kbn/core-status-common'; import { calculateStatus$ } from './status'; import { take } from 'rxjs/operators'; diff --git a/packages/core/saved-objects/core-saved-objects-server-internal/src/status.ts b/packages/core/saved-objects/core-saved-objects-server-internal/src/status.ts index 65c7b21874881a..ab00eeab788885 100644 --- a/packages/core/saved-objects/core-saved-objects-server-internal/src/status.ts +++ b/packages/core/saved-objects/core-saved-objects-server-internal/src/status.ts @@ -8,7 +8,7 @@ import { Observable, combineLatest } from 'rxjs'; import { startWith, map } from 'rxjs/operators'; -import { type ServiceStatus, ServiceStatusLevels } from '@kbn/core-base-common'; +import { type ServiceStatus, ServiceStatusLevels } from '@kbn/core-status-common'; import type { SavedObjectStatusMeta } from '@kbn/core-saved-objects-server'; import type { KibanaMigratorStatus } from '@kbn/core-saved-objects-base-server-internal'; diff --git a/packages/core/saved-objects/core-saved-objects-server-mocks/BUILD.bazel b/packages/core/saved-objects/core-saved-objects-server-mocks/BUILD.bazel index 2720f07e77aa96..717a2bfa6087e0 100644 --- a/packages/core/saved-objects/core-saved-objects-server-mocks/BUILD.bazel +++ b/packages/core/saved-objects/core-saved-objects-server-mocks/BUILD.bazel @@ -36,7 +36,7 @@ NPM_MODULE_EXTRA_FILES = [ RUNTIME_DEPS = [ "@npm//rxjs", - "//packages/core/base/core-base-common", + "//packages/core/status/core-status-common", "//packages/core/saved-objects/core-saved-objects-api-server-mocks", "//packages/core/saved-objects/core-saved-objects-base-server-mocks", "//packages/core/saved-objects/core-saved-objects-import-export-server-mocks", @@ -48,7 +48,7 @@ TYPES_DEPS = [ "@npm//@types/jest", "@npm//rxjs", "//packages/kbn-utility-types:npm_module_types", - "//packages/core/base/core-base-common:npm_module_types", + "//packages/core/status/core-status-common:npm_module_types", "//packages/core/saved-objects/core-saved-objects-server:npm_module_types", "//packages/core/saved-objects/core-saved-objects-server-internal:npm_module_types", "//packages/core/saved-objects/core-saved-objects-api-server-mocks:npm_module_types", diff --git a/packages/core/saved-objects/core-saved-objects-server-mocks/kibana.jsonc b/packages/core/saved-objects/core-saved-objects-server-mocks/kibana.jsonc new file mode 100644 index 00000000000000..c9cb96751b210e --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-server-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-saved-objects-server-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/saved-objects/core-saved-objects-server-mocks/src/saved_objects_service.mock.ts b/packages/core/saved-objects/core-saved-objects-server-mocks/src/saved_objects_service.mock.ts index 3b06cc2c6f3c95..9939e5d3240e97 100644 --- a/packages/core/saved-objects/core-saved-objects-server-mocks/src/saved_objects_service.mock.ts +++ b/packages/core/saved-objects/core-saved-objects-server-mocks/src/saved_objects_service.mock.ts @@ -8,7 +8,7 @@ import { BehaviorSubject } from 'rxjs'; import type { PublicMethodsOf } from '@kbn/utility-types'; -import { ServiceStatusLevels } from '@kbn/core-base-common'; +import { ServiceStatusLevels } from '@kbn/core-status-common'; import type { SavedObjectsServiceSetup, SavedObjectsServiceStart, diff --git a/packages/core/saved-objects/core-saved-objects-server/kibana.jsonc b/packages/core/saved-objects/core-saved-objects-server/kibana.jsonc new file mode 100644 index 00000000000000..8e1a56b92f1f28 --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-server/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-saved-objects-server", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/saved-objects/core-saved-objects-utils-server/kibana.jsonc b/packages/core/saved-objects/core-saved-objects-utils-server/kibana.jsonc new file mode 100644 index 00000000000000..61d87e1fe9bdc7 --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-utils-server/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-saved-objects-utils-server", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/status/core-status-common-internal/BUILD.bazel b/packages/core/status/core-status-common-internal/BUILD.bazel new file mode 100644 index 00000000000000..db1d2ac2b62783 --- /dev/null +++ b/packages/core/status/core-status-common-internal/BUILD.bazel @@ -0,0 +1,115 @@ +load("@npm//@bazel/typescript:index.bzl", "ts_config") +load("@build_bazel_rules_nodejs//:index.bzl", "js_library") +load("//src/dev/bazel:index.bzl", "jsts_transpiler", "pkg_npm", "pkg_npm_types", "ts_project") + +PKG_DIRNAME = "core-status-common-internal" +PKG_REQUIRE_NAME = "@kbn/core-status-common-internal" + +SOURCE_FILES = glob( + [ + "**/*.ts", + "**/*.tsx", + ], + exclude = [ + "**/*.config.js", + "**/*.mock.*", + "**/*.test.*", + "**/*.stories.*", + "**/__snapshots__/**", + "**/integration_tests/**", + "**/mocks/**", + "**/scripts/**", + "**/storybook/**", + "**/test_fixtures/**", + "**/test_helpers/**", + ], +) + +SRCS = SOURCE_FILES + +filegroup( + name = "srcs", + srcs = SRCS, +) + +NPM_MODULE_EXTRA_FILES = [ + "package.json", +] + +RUNTIME_DEPS = [ +] + +TYPES_DEPS = [ + "@npm//@types/node", + "@npm//@types/jest", + "//packages/core/status/core-status-common:npm_module_types", + "//packages/core/metrics/core-metrics-server:npm_module_types", +] + +jsts_transpiler( + name = "target_node", + srcs = SRCS, + build_pkg_name = package_name(), +) + +jsts_transpiler( + name = "target_web", + srcs = SRCS, + build_pkg_name = package_name(), + web = True, +) + +ts_config( + name = "tsconfig", + src = "tsconfig.json", + deps = [ + "//:tsconfig.base.json", + "//:tsconfig.bazel.json", + ], +) + +ts_project( + name = "tsc_types", + args = ['--pretty'], + srcs = SRCS, + deps = TYPES_DEPS, + declaration = True, + declaration_map = True, + emit_declaration_only = True, + out_dir = "target_types", + tsconfig = ":tsconfig", +) + +js_library( + name = PKG_DIRNAME, + srcs = NPM_MODULE_EXTRA_FILES, + deps = RUNTIME_DEPS + [":target_node", ":target_web"], + package_name = PKG_REQUIRE_NAME, + visibility = ["//visibility:public"], +) + +pkg_npm( + name = "npm_module", + deps = [":" + PKG_DIRNAME], +) + +filegroup( + name = "build", + srcs = [":npm_module"], + visibility = ["//visibility:public"], +) + +pkg_npm_types( + name = "npm_module_types", + srcs = SRCS, + deps = [":tsc_types"], + package_name = PKG_REQUIRE_NAME, + tsconfig = ":tsconfig", + visibility = ["//visibility:public"], +) + +filegroup( + name = "build_types", + srcs = [":npm_module_types"], + visibility = ["//visibility:public"], +) diff --git a/packages/core/status/core-status-common-internal/README.md b/packages/core/status/core-status-common-internal/README.md new file mode 100644 index 00000000000000..f4e4af7fd3b3a2 --- /dev/null +++ b/packages/core/status/core-status-common-internal/README.md @@ -0,0 +1,3 @@ +# @kbn/core-status-common-internal + +This package contains the common internal types for Core's `status` domain. diff --git a/packages/kbn-kibana-manifest-parser/index.ts b/packages/core/status/core-status-common-internal/index.ts similarity index 65% rename from packages/kbn-kibana-manifest-parser/index.ts rename to packages/core/status/core-status-common-internal/index.ts index f89c1c8124cce0..1d77cb10e166d1 100644 --- a/packages/kbn-kibana-manifest-parser/index.ts +++ b/packages/core/status/core-status-common-internal/index.ts @@ -6,9 +6,11 @@ * Side Public License, v 1. */ -export { - parseKibanaManifest, - readKibanaManifest, - validateKibanaManifest, -} from './src/parse_kibana_manifest'; -export type { KibanaPackageManifest } from './src/kibana_manifest'; +export type { + StatusInfoCoreStatus, + StatusInfoServiceStatus, + StatusInfo, + StatusResponse, + ServerVersion, + ServerMetrics, +} from './src'; diff --git a/packages/core/status/core-status-common-internal/jest.config.js b/packages/core/status/core-status-common-internal/jest.config.js new file mode 100644 index 00000000000000..f03233015a7976 --- /dev/null +++ b/packages/core/status/core-status-common-internal/jest.config.js @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../../..', + roots: ['/packages/core/status/core-status-common-internal'], +}; diff --git a/packages/core/status/core-status-common-internal/kibana.jsonc b/packages/core/status/core-status-common-internal/kibana.jsonc new file mode 100644 index 00000000000000..3ce3b2bfbcbdb1 --- /dev/null +++ b/packages/core/status/core-status-common-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-status-common-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/status/core-status-common-internal/package.json b/packages/core/status/core-status-common-internal/package.json new file mode 100644 index 00000000000000..7d101cfc7c766c --- /dev/null +++ b/packages/core/status/core-status-common-internal/package.json @@ -0,0 +1,9 @@ +{ + "name": "@kbn/core-status-common-internal", + "private": true, + "version": "1.0.0", + "main": "./target_node/index.js", + "browser": "./target_web/index.js", + "author": "Kibana Core", + "license": "SSPL-1.0 OR Elastic License 2.0" +} diff --git a/packages/core/status/core-status-common-internal/src/index.ts b/packages/core/status/core-status-common-internal/src/index.ts new file mode 100644 index 00000000000000..4d2ad5cc82485a --- /dev/null +++ b/packages/core/status/core-status-common-internal/src/index.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 + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export type { + StatusInfo, + StatusInfoCoreStatus, + StatusInfoServiceStatus, + StatusResponse, + ServerVersion, + ServerMetrics, +} from './status'; diff --git a/src/core/types/status.ts b/packages/core/status/core-status-common-internal/src/status.ts similarity index 57% rename from src/core/types/status.ts rename to packages/core/status/core-status-common-internal/src/status.ts index ad5c5b13c9a3a2..7c94080671fd13 100644 --- a/src/core/types/status.ts +++ b/packages/core/status/core-status-common-internal/src/status.ts @@ -6,29 +6,19 @@ * Side Public License, v 1. */ -import type { - CoreStatus as CoreStatusFromServer, - ServiceStatus as ServiceStatusFromServer, - ServiceStatusLevel as ServiceStatusLevelFromServer, - OpsMetrics, -} from '../server'; +import type { ServiceStatusLevelId, ServiceStatus, CoreStatus } from '@kbn/core-status-common'; +import type { OpsMetrics } from '@kbn/core-metrics-server'; -/** - * We need this type to convert the object `ServiceStatusLevel` to a union of the possible strings. - * This is because of the "stringification" that occurs when serving HTTP requests. - */ -export type ServiceStatusLevel = ReturnType; - -export interface ServiceStatus extends Omit { - level: ServiceStatusLevel; +export interface StatusInfoServiceStatus extends Omit { + level: ServiceStatusLevelId; } /** * Copy all the services listed in CoreStatus with their specific ServiceStatus declarations * but overwriting the `level` to its stringified version. */ -export type CoreStatus = { - [ServiceName in keyof CoreStatusFromServer]: ServiceStatus; +export type StatusInfoCoreStatus = { + [ServiceName in keyof CoreStatus]: StatusInfoServiceStatus; }; export type ServerMetrics = Omit & { @@ -47,9 +37,9 @@ export interface ServerVersion { } export interface StatusInfo { - overall: ServiceStatus; - core: CoreStatus; - plugins: Record; + overall: StatusInfoServiceStatus; + core: StatusInfoCoreStatus; + plugins: Record; } export interface StatusResponse { diff --git a/packages/kbn-kibana-manifest-parser/tsconfig.json b/packages/core/status/core-status-common-internal/tsconfig.json similarity index 72% rename from packages/kbn-kibana-manifest-parser/tsconfig.json rename to packages/core/status/core-status-common-internal/tsconfig.json index ad1611b40c04e4..26b4c7aca3a676 100644 --- a/packages/kbn-kibana-manifest-parser/tsconfig.json +++ b/packages/core/status/core-status-common-internal/tsconfig.json @@ -1,11 +1,9 @@ { - "extends": "../../tsconfig.bazel.json", + "extends": "../../../../tsconfig.bazel.json", "compilerOptions": { "declaration": true, "declarationMap": true, "emitDeclarationOnly": true, - "allowJs": true, - "checkJs": true, "outDir": "target_types", "stripInternal": false, "types": [ @@ -14,7 +12,7 @@ ] }, "include": [ - "**/*.js", "**/*.ts", + "**/*.tsx", ] } diff --git a/packages/core/status/core-status-common/BUILD.bazel b/packages/core/status/core-status-common/BUILD.bazel new file mode 100644 index 00000000000000..f13519217c685f --- /dev/null +++ b/packages/core/status/core-status-common/BUILD.bazel @@ -0,0 +1,116 @@ +load("@npm//@bazel/typescript:index.bzl", "ts_config") +load("@build_bazel_rules_nodejs//:index.bzl", "js_library") +load("//src/dev/bazel:index.bzl", "jsts_transpiler", "pkg_npm", "pkg_npm_types", "ts_project") + +PKG_DIRNAME = "core-status-common" +PKG_REQUIRE_NAME = "@kbn/core-status-common" + +SOURCE_FILES = glob( + [ + "**/*.ts", + "**/*.tsx", + ], + exclude = [ + "**/*.config.js", + "**/*.mock.*", + "**/*.test.*", + "**/*.stories.*", + "**/__snapshots__/**", + "**/integration_tests/**", + "**/mocks/**", + "**/scripts/**", + "**/storybook/**", + "**/test_fixtures/**", + "**/test_helpers/**", + ], +) + +SRCS = SOURCE_FILES + +filegroup( + name = "srcs", + srcs = SRCS, +) + +NPM_MODULE_EXTRA_FILES = [ + "package.json", +] + +RUNTIME_DEPS = [ + "@npm//react", + "//packages/kbn-std", +] + +TYPES_DEPS = [ + "@npm//@types/node", + "@npm//@types/jest", + "//packages/kbn-std:npm_module_types", +] + +jsts_transpiler( + name = "target_node", + srcs = SRCS, + build_pkg_name = package_name(), +) + +jsts_transpiler( + name = "target_web", + srcs = SRCS, + build_pkg_name = package_name(), + web = True, +) + +ts_config( + name = "tsconfig", + src = "tsconfig.json", + deps = [ + "//:tsconfig.base.json", + "//:tsconfig.bazel.json", + ], +) + +ts_project( + name = "tsc_types", + args = ['--pretty'], + srcs = SRCS, + deps = TYPES_DEPS, + declaration = True, + declaration_map = True, + emit_declaration_only = True, + out_dir = "target_types", + tsconfig = ":tsconfig", +) + +js_library( + name = PKG_DIRNAME, + srcs = NPM_MODULE_EXTRA_FILES, + deps = RUNTIME_DEPS + [":target_node", ":target_web"], + package_name = PKG_REQUIRE_NAME, + visibility = ["//visibility:public"], +) + +pkg_npm( + name = "npm_module", + deps = [":" + PKG_DIRNAME], +) + +filegroup( + name = "build", + srcs = [":npm_module"], + visibility = ["//visibility:public"], +) + +pkg_npm_types( + name = "npm_module_types", + srcs = SRCS, + deps = [":tsc_types"], + package_name = PKG_REQUIRE_NAME, + tsconfig = ":tsconfig", + visibility = ["//visibility:public"], +) + +filegroup( + name = "build_types", + srcs = [":npm_module_types"], + visibility = ["//visibility:public"], +) diff --git a/packages/core/status/core-status-common/README.md b/packages/core/status/core-status-common/README.md new file mode 100644 index 00000000000000..7a13938f39c10d --- /dev/null +++ b/packages/core/status/core-status-common/README.md @@ -0,0 +1,3 @@ +# @kbn/core-status-common + +This package contains the common public types for Core's `status` domain. diff --git a/packages/core/status/core-status-common/index.ts b/packages/core/status/core-status-common/index.ts new file mode 100644 index 00000000000000..78e04a1aa79361 --- /dev/null +++ b/packages/core/status/core-status-common/index.ts @@ -0,0 +1,10 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export { ServiceStatusLevels } from './src'; +export type { ServiceStatus, ServiceStatusLevel, ServiceStatusLevelId, CoreStatus } from './src'; diff --git a/packages/core/status/core-status-common/jest.config.js b/packages/core/status/core-status-common/jest.config.js new file mode 100644 index 00000000000000..f03233015a7976 --- /dev/null +++ b/packages/core/status/core-status-common/jest.config.js @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../../..', + roots: ['/packages/core/status/core-status-common-internal'], +}; diff --git a/packages/core/status/core-status-common/kibana.jsonc b/packages/core/status/core-status-common/kibana.jsonc new file mode 100644 index 00000000000000..13d67c52659ca1 --- /dev/null +++ b/packages/core/status/core-status-common/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-status-common", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/status/core-status-common/package.json b/packages/core/status/core-status-common/package.json new file mode 100644 index 00000000000000..19a21ce0125ecf --- /dev/null +++ b/packages/core/status/core-status-common/package.json @@ -0,0 +1,9 @@ +{ + "name": "@kbn/core-status-common", + "private": true, + "version": "1.0.0", + "main": "./target_node/index.js", + "browser": "./target_web/index.js", + "author": "Kibana Core", + "license": "SSPL-1.0 OR Elastic License 2.0" +} diff --git a/packages/core/status/core-status-common/src/core_status.ts b/packages/core/status/core-status-common/src/core_status.ts new file mode 100644 index 00000000000000..0d852b7f1e3e4e --- /dev/null +++ b/packages/core/status/core-status-common/src/core_status.ts @@ -0,0 +1,23 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { ServiceStatus } from './service_status'; + +/** + * Status of core services. + * + * @internalRemarks + * Only contains entries for backend services that could have a non-available `status`. + * For example, `context` cannot possibly be broken, so it is not included. + * + * @public + */ +export interface CoreStatus { + elasticsearch: ServiceStatus; + savedObjects: ServiceStatus; +} diff --git a/packages/core/status/core-status-common/src/index.ts b/packages/core/status/core-status-common/src/index.ts new file mode 100644 index 00000000000000..64b3cf7733524c --- /dev/null +++ b/packages/core/status/core-status-common/src/index.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 + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export { ServiceStatusLevels } from './service_status'; +export type { ServiceStatus, ServiceStatusLevel, ServiceStatusLevelId } from './service_status'; +export type { CoreStatus } from './core_status'; diff --git a/packages/core/base/core-base-common/src/service_status.ts b/packages/core/status/core-status-common/src/service_status.ts similarity index 94% rename from packages/core/base/core-base-common/src/service_status.ts rename to packages/core/status/core-status-common/src/service_status.ts index 4c9539f015d86a..e976bd16c765df 100644 --- a/packages/core/base/core-base-common/src/service_status.ts +++ b/packages/core/status/core-status-common/src/service_status.ts @@ -39,6 +39,13 @@ export interface ServiceStatus | unknown = unkn meta?: Meta; } +/** + * Possible values for the ID of a {@link ServiceStatusLevel} + * + * @public + */ +export type ServiceStatusLevelId = 'available' | 'degraded' | 'unavailable' | 'critical'; + /** * The current "level" of availability of a service. * diff --git a/packages/kbn-jsonc/tsconfig.json b/packages/core/status/core-status-common/tsconfig.json similarity index 71% rename from packages/kbn-jsonc/tsconfig.json rename to packages/core/status/core-status-common/tsconfig.json index 7057d75ce49524..26b4c7aca3a676 100644 --- a/packages/kbn-jsonc/tsconfig.json +++ b/packages/core/status/core-status-common/tsconfig.json @@ -1,11 +1,9 @@ { - "extends": "../../tsconfig.bazel.json", + "extends": "../../../../tsconfig.bazel.json", "compilerOptions": { "declaration": true, "declarationMap": true, "emitDeclarationOnly": true, - "allowJs": true, - "checkJs": true, "outDir": "target_types", "stripInternal": false, "types": [ @@ -14,6 +12,7 @@ ] }, "include": [ - "**/*.js" + "**/*.ts", + "**/*.tsx", ] } diff --git a/packages/core/status/core-status-server-internal/BUILD.bazel b/packages/core/status/core-status-server-internal/BUILD.bazel new file mode 100644 index 00000000000000..7b199378c4881e --- /dev/null +++ b/packages/core/status/core-status-server-internal/BUILD.bazel @@ -0,0 +1,134 @@ +load("@npm//@bazel/typescript:index.bzl", "ts_config") +load("@build_bazel_rules_nodejs//:index.bzl", "js_library") +load("//src/dev/bazel:index.bzl", "jsts_transpiler", "pkg_npm", "pkg_npm_types", "ts_project") + +PKG_DIRNAME = "core-status-server-internal" +PKG_REQUIRE_NAME = "@kbn/core-status-server-internal" + +SOURCE_FILES = glob( + [ + "**/*.ts", + ], + exclude = [ + "**/*.config.js", + "**/*.mock.*", + "**/*.test.*", + "**/*.stories.*", + "**/__snapshots__/**", + "**/integration_tests/**", + "**/mocks/**", + "**/scripts/**", + "**/storybook/**", + "**/test_fixtures/**", + "**/test_helpers/**", + ], +) + +SRCS = SOURCE_FILES + +filegroup( + name = "srcs", + srcs = SRCS, +) + +NPM_MODULE_EXTRA_FILES = [ + "package.json", +] + +RUNTIME_DEPS = [ + "@npm//rxjs", + "@npm//lodash", + "//packages/kbn-config-schema", + "//packages/kbn-std", + "//packages/kbn-i18n", + "//packages/core/status/core-status-common", +] + +TYPES_DEPS = [ + "@npm//@types/node", + "@npm//@types/jest", + "@npm//rxjs", + "@npm//lodash", + "//packages/kbn-config-schema:npm_module_types", + "//packages/kbn-config:npm_module_types", + "//packages/kbn-std:npm_module_types", + "//packages/kbn-logging:npm_module_types", + "//packages/kbn-i18n:npm_module_types", + "//packages/analytics/client:npm_module_types", + "//packages/core/base/core-base-common:npm_module_types", + "//packages/core/base/core-base-server-internal:npm_module_types", + "//packages/core/http/core-http-server:npm_module_types", + "//packages/core/http/core-http-server-internal:npm_module_types", + "//packages/core/metrics/core-metrics-server:npm_module_types", + "//packages/core/metrics/core-metrics-server-internal:npm_module_types", + "//packages/core/usage-data/core-usage-data-server:npm_module_types", + "//packages/core/usage-data/core-usage-data-server-internal:npm_module_types", + "//packages/core/analytics/core-analytics-server:npm_module_types", + "//packages/core/environment/core-environment-server-internal:npm_module_types", + "//packages/core/elasticsearch/core-elasticsearch-server-internal:npm_module_types", + "//packages/core/saved-objects/core-saved-objects-server-internal:npm_module_types", + "//packages/core/status/core-status-server:npm_module_types", + "//packages/core/status/core-status-common:npm_module_types", + "//packages/core/status/core-status-common-internal:npm_module_types", +] + +jsts_transpiler( + name = "target_node", + srcs = SRCS, + build_pkg_name = package_name(), +) + +ts_config( + name = "tsconfig", + src = "tsconfig.json", + deps = [ + "//:tsconfig.base.json", + "//:tsconfig.bazel.json", + ], +) + +ts_project( + name = "tsc_types", + args = ['--pretty'], + srcs = SRCS, + deps = TYPES_DEPS, + declaration = True, + declaration_map = True, + emit_declaration_only = True, + out_dir = "target_types", + tsconfig = ":tsconfig", +) + +js_library( + name = PKG_DIRNAME, + srcs = NPM_MODULE_EXTRA_FILES, + deps = RUNTIME_DEPS + [":target_node"], + package_name = PKG_REQUIRE_NAME, + visibility = ["//visibility:public"], +) + +pkg_npm( + name = "npm_module", + deps = [":" + PKG_DIRNAME], +) + +filegroup( + name = "build", + srcs = [":npm_module"], + visibility = ["//visibility:public"], +) + +pkg_npm_types( + name = "npm_module_types", + srcs = SRCS, + deps = [":tsc_types"], + package_name = PKG_REQUIRE_NAME, + tsconfig = ":tsconfig", + visibility = ["//visibility:public"], +) + +filegroup( + name = "build_types", + srcs = [":npm_module_types"], + visibility = ["//visibility:public"], +) diff --git a/packages/core/status/core-status-server-internal/README.md b/packages/core/status/core-status-server-internal/README.md new file mode 100644 index 00000000000000..cdc068f6bead1e --- /dev/null +++ b/packages/core/status/core-status-server-internal/README.md @@ -0,0 +1,3 @@ +# @kbn/core-status-server-internal + +This package contains the internal types and implementation for Core's server-side `status` service. diff --git a/packages/core/status/core-status-server-internal/index.ts b/packages/core/status/core-status-server-internal/index.ts new file mode 100644 index 00000000000000..19876f99f4a865 --- /dev/null +++ b/packages/core/status/core-status-server-internal/index.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export { statusConfig, StatusService } from './src'; +export type { StatusConfigType, InternalStatusServiceSetup, StatusServiceSetupDeps } from './src'; + +// exported only for integration tests +export { registerStatusRoute } from './src/routes/status'; diff --git a/packages/core/status/core-status-server-internal/jest.config.js b/packages/core/status/core-status-server-internal/jest.config.js new file mode 100644 index 00000000000000..2bb0f4715da10b --- /dev/null +++ b/packages/core/status/core-status-server-internal/jest.config.js @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +module.exports = { + preset: '@kbn/test/jest_node', + rootDir: '../../../..', + roots: ['/packages/core/status/core-status-server-internal'], +}; diff --git a/packages/core/status/core-status-server-internal/kibana.jsonc b/packages/core/status/core-status-server-internal/kibana.jsonc new file mode 100644 index 00000000000000..9ed3627ce73ed9 --- /dev/null +++ b/packages/core/status/core-status-server-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-status-server-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/status/core-status-server-internal/package.json b/packages/core/status/core-status-server-internal/package.json new file mode 100644 index 00000000000000..495d8c56d3815e --- /dev/null +++ b/packages/core/status/core-status-server-internal/package.json @@ -0,0 +1,8 @@ +{ + "name": "@kbn/core-status-server-internal", + "private": true, + "version": "1.0.0", + "main": "./target_node/index.js", + "author": "Kibana Core", + "license": "SSPL-1.0 OR Elastic License 2.0" +} diff --git a/src/core/server/status/cached_plugins_status.ts b/packages/core/status/core-status-server-internal/src/cached_plugins_status.ts similarity index 94% rename from src/core/server/status/cached_plugins_status.ts rename to packages/core/status/core-status-server-internal/src/cached_plugins_status.ts index 4f574a6382106c..20cc30d83176e6 100644 --- a/src/core/server/status/cached_plugins_status.ts +++ b/packages/core/status/core-status-server-internal/src/cached_plugins_status.ts @@ -6,10 +6,9 @@ * Side Public License, v 1. */ -import { Observable } from 'rxjs'; - +import type { Observable } from 'rxjs'; import type { PluginName } from '@kbn/core-base-common'; -import { type ServiceStatus } from './types'; +import type { ServiceStatus } from '@kbn/core-status-common'; import { type Deps, PluginsStatusService as BasePluginsStatusService } from './plugins_status'; diff --git a/src/core/server/status/get_summary_status.test.ts b/packages/core/status/core-status-server-internal/src/get_summary_status.test.ts similarity index 98% rename from src/core/server/status/get_summary_status.test.ts rename to packages/core/status/core-status-server-internal/src/get_summary_status.test.ts index 2c91aa8c7b16ae..2bb692bfc311be 100644 --- a/src/core/server/status/get_summary_status.test.ts +++ b/packages/core/status/core-status-server-internal/src/get_summary_status.test.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { ServiceStatus, ServiceStatusLevels } from './types'; +import { ServiceStatus, ServiceStatusLevels } from '@kbn/core-status-common'; import { getSummaryStatus } from './get_summary_status'; describe('getSummaryStatus', () => { diff --git a/src/core/server/status/get_summary_status.ts b/packages/core/status/core-status-server-internal/src/get_summary_status.ts similarity index 95% rename from src/core/server/status/get_summary_status.ts rename to packages/core/status/core-status-server-internal/src/get_summary_status.ts index 1dc939ce3f80c1..083364fad2fd2d 100644 --- a/src/core/server/status/get_summary_status.ts +++ b/packages/core/status/core-status-server-internal/src/get_summary_status.ts @@ -6,7 +6,11 @@ * Side Public License, v 1. */ -import { ServiceStatus, ServiceStatusLevels, ServiceStatusLevel } from './types'; +import { + ServiceStatusLevels, + type ServiceStatus, + type ServiceStatusLevel, +} from '@kbn/core-status-common'; /** * Returns a single {@link ServiceStatus} that summarizes the most severe status level from a group of statuses. diff --git a/packages/core/status/core-status-server-internal/src/index.ts b/packages/core/status/core-status-server-internal/src/index.ts new file mode 100644 index 00000000000000..0604754f5c1de5 --- /dev/null +++ b/packages/core/status/core-status-server-internal/src/index.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export { StatusService } from './status_service'; +export type { StatusServiceSetupDeps } from './status_service'; +export { statusConfig } from './status_config'; +export type { StatusConfigType } from './status_config'; +export type { InternalStatusServiceSetup } from './types'; diff --git a/src/core/server/status/legacy_status.test.ts b/packages/core/status/core-status-server-internal/src/legacy_status.test.ts similarity index 97% rename from src/core/server/status/legacy_status.test.ts rename to packages/core/status/core-status-server-internal/src/legacy_status.test.ts index 61c356e514e5f0..f20a5717864300 100644 --- a/src/core/server/status/legacy_status.test.ts +++ b/packages/core/status/core-status-server-internal/src/legacy_status.test.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { ServiceStatus, ServiceStatusLevels } from './types'; +import { ServiceStatus, ServiceStatusLevels } from '@kbn/core-status-common'; import { calculateLegacyStatus } from './legacy_status'; const available: ServiceStatus = { level: ServiceStatusLevels.available, summary: 'Available' }; diff --git a/src/core/server/status/legacy_status.ts b/packages/core/status/core-status-server-internal/src/legacy_status.ts similarity index 97% rename from src/core/server/status/legacy_status.ts rename to packages/core/status/core-status-server-internal/src/legacy_status.ts index b9ae0461d91d70..f154374d5470ec 100644 --- a/src/core/server/status/legacy_status.ts +++ b/packages/core/status/core-status-server-internal/src/legacy_status.ts @@ -9,9 +9,8 @@ import { pick } from 'lodash'; import { i18n } from '@kbn/i18n'; import { deepFreeze } from '@kbn/std'; - import type { PluginName } from '@kbn/core-base-common'; -import { ServiceStatusLevels, ServiceStatus, CoreStatus } from './types'; +import { ServiceStatusLevels, type ServiceStatus, type CoreStatus } from '@kbn/core-status-common'; interface Deps { overall: ServiceStatus; diff --git a/src/core/server/status/log_overall_status.test.ts b/packages/core/status/core-status-server-internal/src/log_overall_status.test.ts similarity index 97% rename from src/core/server/status/log_overall_status.test.ts rename to packages/core/status/core-status-server-internal/src/log_overall_status.test.ts index b656b16a9e00b6..f74fb472d08f6f 100644 --- a/src/core/server/status/log_overall_status.test.ts +++ b/packages/core/status/core-status-server-internal/src/log_overall_status.test.ts @@ -7,7 +7,7 @@ */ import { TestScheduler } from 'rxjs/testing'; -import { ServiceStatus, ServiceStatusLevels } from './types'; +import { ServiceStatus, ServiceStatusLevels } from '@kbn/core-status-common'; import { getOverallStatusChanges } from './log_overall_status'; const getTestScheduler = () => diff --git a/src/core/server/status/log_overall_status.ts b/packages/core/status/core-status-server-internal/src/log_overall_status.ts similarity index 94% rename from src/core/server/status/log_overall_status.ts rename to packages/core/status/core-status-server-internal/src/log_overall_status.ts index c77f634046be15..e69fad24c12e04 100644 --- a/src/core/server/status/log_overall_status.ts +++ b/packages/core/status/core-status-server-internal/src/log_overall_status.ts @@ -8,7 +8,7 @@ import { Observable } from 'rxjs'; import { distinctUntilChanged, pairwise, startWith, takeUntil, map } from 'rxjs/operators'; -import { ServiceStatus } from './types'; +import type { ServiceStatus } from '@kbn/core-status-common'; export const getOverallStatusChanges = ( overall$: Observable, diff --git a/src/core/server/status/plugins_status.test.ts b/packages/core/status/core-status-server-internal/src/plugins_status.test.ts similarity index 99% rename from src/core/server/status/plugins_status.test.ts rename to packages/core/status/core-status-server-internal/src/plugins_status.test.ts index eaab8841563b57..b84151fb9da83e 100644 --- a/src/core/server/status/plugins_status.test.ts +++ b/packages/core/status/core-status-server-internal/src/plugins_status.test.ts @@ -9,9 +9,9 @@ import type { PluginName } from '@kbn/core-base-common'; import { PluginsStatusService } from './plugins_status'; import { of, Observable, BehaviorSubject, ReplaySubject } from 'rxjs'; -import { ServiceStatusLevels, CoreStatus, ServiceStatus } from './types'; +import { ServiceStatusLevels, CoreStatus, ServiceStatus } from '@kbn/core-status-common'; import { first, skip } from 'rxjs/operators'; -import { ServiceStatusLevelSnapshotSerializer } from './test_utils'; +import { ServiceStatusLevelSnapshotSerializer } from './test_helpers'; expect.addSnapshotSerializer(ServiceStatusLevelSnapshotSerializer); diff --git a/src/core/server/status/plugins_status.ts b/packages/core/status/core-status-server-internal/src/plugins_status.ts similarity index 99% rename from src/core/server/status/plugins_status.ts rename to packages/core/status/core-status-server-internal/src/plugins_status.ts index a3e52941577800..58272636bfe854 100644 --- a/src/core/server/status/plugins_status.ts +++ b/packages/core/status/core-status-server-internal/src/plugins_status.ts @@ -5,6 +5,7 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ + import { BehaviorSubject, Observable, ReplaySubject, Subscription } from 'rxjs'; import { map, @@ -16,9 +17,8 @@ import { } from 'rxjs/operators'; import { sortBy } from 'lodash'; import { isDeepStrictEqual } from 'util'; - import type { PluginName } from '@kbn/core-base-common'; -import { type ServiceStatus, type CoreStatus, ServiceStatusLevels } from './types'; +import { ServiceStatusLevels, type CoreStatus, type ServiceStatus } from '@kbn/core-status-common'; import { getSummaryStatus } from './get_summary_status'; const STATUS_TIMEOUT_MS = 30 * 1000; // 30 seconds @@ -43,6 +43,7 @@ interface PluginData { derivedStatus: ServiceStatus; }; } + interface PluginStatus { [name: PluginName]: ServiceStatus; } diff --git a/src/core/server/status/routes/index.ts b/packages/core/status/core-status-server-internal/src/routes/index.ts similarity index 100% rename from src/core/server/status/routes/index.ts rename to packages/core/status/core-status-server-internal/src/routes/index.ts diff --git a/src/core/server/status/routes/status.ts b/packages/core/status/core-status-server-internal/src/routes/status.ts similarity index 97% rename from src/core/server/status/routes/status.ts rename to packages/core/status/core-status-server-internal/src/routes/status.ts index 5033f2e9beacef..34a5a9b4dcd20f 100644 --- a/src/core/server/status/routes/status.ts +++ b/packages/core/status/core-status-server-internal/src/routes/status.ts @@ -8,15 +8,14 @@ import { Observable, combineLatest, ReplaySubject, firstValueFrom } from 'rxjs'; import { schema } from '@kbn/config-schema'; -import { PackageInfo } from '@kbn/config'; - +import type { PackageInfo } from '@kbn/config'; import type { PluginName } from '@kbn/core-base-common'; import type { IRouter } from '@kbn/core-http-server'; import type { MetricsServiceSetup } from '@kbn/core-metrics-server'; import type { CoreIncrementUsageCounter } from '@kbn/core-usage-data-server'; -import { ServiceStatus, CoreStatus, ServiceStatusLevels } from '../types'; +import type { StatusResponse } from '@kbn/core-status-common-internal'; +import { ServiceStatus, CoreStatus, ServiceStatusLevels } from '@kbn/core-status-common'; import { calculateLegacyStatus, LegacyStatusInfo } from '../legacy_status'; -import { StatusResponse } from '../../../types/status'; const SNAPSHOT_POSTFIX = /-SNAPSHOT$/; diff --git a/src/core/server/status/status_config.ts b/packages/core/status/core-status-server-internal/src/status_config.ts similarity index 90% rename from src/core/server/status/status_config.ts rename to packages/core/status/core-status-server-internal/src/status_config.ts index 09e987a4e8d379..fd08fb1ad8b25d 100644 --- a/src/core/server/status/status_config.ts +++ b/packages/core/status/core-status-server-internal/src/status_config.ts @@ -15,7 +15,7 @@ const statusConfigSchema = schema.object({ export type StatusConfigType = TypeOf; -export const config: ServiceConfigDescriptor = { +export const statusConfig: ServiceConfigDescriptor = { path: 'status', schema: statusConfigSchema, }; diff --git a/src/core/server/status/status_service.test.ts b/packages/core/status/core-status-server-internal/src/status_service.test.ts similarity index 97% rename from src/core/server/status/status_service.test.ts rename to packages/core/status/core-status-server-internal/src/status_service.test.ts index a3ca69ca4f243b..cbd811ebdb72be 100644 --- a/src/core/server/status/status_service.test.ts +++ b/packages/core/status/core-status-server-internal/src/status_service.test.ts @@ -8,24 +8,20 @@ import { of, BehaviorSubject, firstValueFrom } from 'rxjs'; -import { - ServiceStatus, - ServiceStatusLevels, - CoreStatus, - InternalStatusServiceSetup, -} from './types'; -import { StatusService } from './status_service'; +import { ServiceStatus, ServiceStatusLevels, CoreStatus } from '@kbn/core-status-common'; +import { InternalStatusServiceSetup } from './types'; +import { StatusService, StatusServiceSetupDeps } from './status_service'; import { first, take, toArray } from 'rxjs/operators'; import { mockCoreContext } from '@kbn/core-base-server-mocks'; import { environmentServiceMock } from '@kbn/core-environment-server-mocks'; import { mockRouter, RouterMock } from '@kbn/core-http-router-server-mocks'; import { httpServiceMock } from '@kbn/core-http-server-mocks'; -import { ServiceStatusLevelSnapshotSerializer } from './test_utils'; +import { ServiceStatusLevelSnapshotSerializer } from './test_helpers'; import { metricsServiceMock } from '@kbn/core-metrics-server-mocks'; import { configServiceMock } from '@kbn/config-mocks'; import { coreUsageDataServiceMock } from '@kbn/core-usage-data-server-mocks'; import { analyticsServiceMock } from '@kbn/core-analytics-server-mocks'; -import { AnalyticsServiceSetup } from '..'; +import type { AnalyticsServiceSetup } from '@kbn/core-analytics-server'; expect.addSnapshotSerializer(ServiceStatusLevelSnapshotSerializer); @@ -51,8 +47,7 @@ describe('StatusService', () => { summary: 'This is critical!', }; - type SetupDeps = Parameters[0]; - const setupDeps = (overrides: Partial): SetupDeps => { + const setupDeps = (overrides: Partial): StatusServiceSetupDeps => { return { analytics: analyticsServiceMock.createAnalyticsServiceSetup(), elasticsearch: { diff --git a/src/core/server/status/status_service.ts b/packages/core/status/core-status-server-internal/src/status_service.ts similarity index 95% rename from src/core/server/status/status_service.ts rename to packages/core/status/core-status-server-internal/src/status_service.ts index 8d036177c6e067..4eb96e73e1b1db 100644 --- a/src/core/server/status/status_service.ts +++ b/packages/core/status/core-status-server-internal/src/status_service.ts @@ -19,7 +19,7 @@ import { map, distinctUntilChanged, shareReplay, debounceTime, takeUntil } from import { isDeepStrictEqual } from 'util'; import type { RootSchema } from '@kbn/analytics-client'; -import { Logger, LogMeta } from '@kbn/logging'; +import type { Logger, LogMeta } from '@kbn/logging'; import type { CoreContext, CoreService } from '@kbn/core-base-server-internal'; import type { PluginName } from '@kbn/core-base-common'; import type { AnalyticsServiceSetup } from '@kbn/core-analytics-server'; @@ -29,10 +29,11 @@ import type { InternalElasticsearchServiceSetup } from '@kbn/core-elasticsearch- import type { InternalMetricsServiceSetup } from '@kbn/core-metrics-server-internal'; import type { InternalSavedObjectsServiceSetup } from '@kbn/core-saved-objects-server-internal'; import type { InternalCoreUsageDataSetup } from '@kbn/core-usage-data-base-server-internal'; +import type { ServiceStatus, CoreStatus } from '@kbn/core-status-common'; import { registerStatusRoute } from './routes'; -import { config, StatusConfigType } from './status_config'; -import { ServiceStatus, CoreStatus, InternalStatusServiceSetup } from './types'; +import { statusConfig as config, StatusConfigType } from './status_config'; +import type { InternalStatusServiceSetup } from './types'; import { getSummaryStatus } from './get_summary_status'; import { PluginsStatusService } from './cached_plugins_status'; import { getOverallStatusChanges } from './log_overall_status'; @@ -46,7 +47,7 @@ interface StatusAnalyticsPayload { overall_status_summary: string; } -export interface SetupDeps { +export interface StatusServiceSetupDeps { analytics: AnalyticsServiceSetup; elasticsearch: Pick; environment: InternalEnvironmentServiceSetup; @@ -80,7 +81,7 @@ export class StatusService implements CoreService { savedObjects, environment, coreUsageData, - }: SetupDeps) { + }: StatusServiceSetupDeps) { const statusConfig = await firstValueFrom(this.config$); const core$ = this.setupCoreStatus({ elasticsearch, savedObjects }); this.pluginsStatus = new PluginsStatusService({ core$, pluginDependencies }); @@ -200,7 +201,7 @@ export class StatusService implements CoreService { private setupCoreStatus({ elasticsearch, savedObjects, - }: Pick): Observable { + }: Pick): Observable { return combineLatest([elasticsearch.status$, savedObjects.status$]).pipe( map(([elasticsearchStatus, savedObjectsStatus]) => ({ elasticsearch: elasticsearchStatus, diff --git a/src/core/server/status/index.ts b/packages/core/status/core-status-server-internal/src/test_helpers/index.ts similarity index 75% rename from src/core/server/status/index.ts rename to packages/core/status/core-status-server-internal/src/test_helpers/index.ts index beb20d57b8582e..27bc0a877cce97 100644 --- a/src/core/server/status/index.ts +++ b/packages/core/status/core-status-server-internal/src/test_helpers/index.ts @@ -6,6 +6,4 @@ * Side Public License, v 1. */ -export { StatusService } from './status_service'; -export { config } from './status_config'; -export * from './types'; +export { ServiceStatusLevelSnapshotSerializer } from './test_utils'; diff --git a/src/core/server/status/test_utils.ts b/packages/core/status/core-status-server-internal/src/test_helpers/test_utils.ts similarity index 87% rename from src/core/server/status/test_utils.ts rename to packages/core/status/core-status-server-internal/src/test_helpers/test_utils.ts index e75ce9412de74d..4b46ac23f5c8d9 100644 --- a/src/core/server/status/test_utils.ts +++ b/packages/core/status/core-status-server-internal/src/test_helpers/test_utils.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { ServiceStatusLevels, ServiceStatusLevel } from './types'; +import { ServiceStatusLevels, ServiceStatusLevel } from '@kbn/core-status-common'; export const ServiceStatusLevelSnapshotSerializer: jest.SnapshotSerializerPlugin = { test: (val: any) => Object.values(ServiceStatusLevels).includes(val), diff --git a/packages/core/status/core-status-server-internal/src/types.ts b/packages/core/status/core-status-server-internal/src/types.ts new file mode 100644 index 00000000000000..520a313bc97863 --- /dev/null +++ b/packages/core/status/core-status-server-internal/src/types.ts @@ -0,0 +1,28 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { Observable } from 'rxjs'; +import type { PluginName } from '@kbn/core-base-common'; +import type { ServiceStatus } from '@kbn/core-status-common'; +import type { StatusServiceSetup } from '@kbn/core-status-server'; + +/** @internal */ +export interface InternalStatusServiceSetup + extends Pick { + /** + * Overall status of core's service. + */ + coreOverall$: Observable; + + // Namespaced under `plugins` key to improve clarity that these are APIs for plugins specifically. + plugins: { + set(plugin: PluginName, status$: Observable): void; + getDependenciesStatus$(plugin: PluginName): Observable>; + getDerivedStatus$(plugin: PluginName): Observable; + }; +} diff --git a/packages/core/status/core-status-server-internal/tsconfig.json b/packages/core/status/core-status-server-internal/tsconfig.json new file mode 100644 index 00000000000000..71bb40fe57f3f4 --- /dev/null +++ b/packages/core/status/core-status-server-internal/tsconfig.json @@ -0,0 +1,17 @@ +{ + "extends": "../../../../tsconfig.bazel.json", + "compilerOptions": { + "declaration": true, + "declarationMap": true, + "emitDeclarationOnly": true, + "outDir": "target_types", + "stripInternal": false, + "types": [ + "jest", + "node" + ] + }, + "include": [ + "**/*.ts", + ] +} diff --git a/packages/kbn-kibana-manifest-parser/BUILD.bazel b/packages/core/status/core-status-server-mocks/BUILD.bazel similarity index 66% rename from packages/kbn-kibana-manifest-parser/BUILD.bazel rename to packages/core/status/core-status-server-mocks/BUILD.bazel index aff27a65537ad1..54472c706546b7 100644 --- a/packages/kbn-kibana-manifest-parser/BUILD.bazel +++ b/packages/core/status/core-status-server-mocks/BUILD.bazel @@ -2,17 +2,15 @@ load("@npm//@bazel/typescript:index.bzl", "ts_config") load("@build_bazel_rules_nodejs//:index.bzl", "js_library") load("//src/dev/bazel:index.bzl", "jsts_transpiler", "pkg_npm", "pkg_npm_types", "ts_project") -PKG_DIRNAME = "kbn-kibana-manifest-parser" -PKG_REQUIRE_NAME = "@kbn/kibana-manifest-parser" +PKG_DIRNAME = "core-status-server-mocks" +PKG_REQUIRE_NAME = "@kbn/core-status-server-mocks" SOURCE_FILES = glob( [ - "**/*.js", "**/*.ts", ], exclude = [ "**/*.config.js", - "**/*.mock.*", "**/*.test.*", "**/*.stories.*", "**/__snapshots__/**", @@ -36,32 +34,18 @@ NPM_MODULE_EXTRA_FILES = [ "package.json", ] -# In this array place runtime dependencies, including other packages and NPM packages -# which must be available for this code to run. -# -# To reference other packages use: -# "//repo/relative/path/to/package" -# eg. "//packages/kbn-utils" -# -# To reference a NPM package use: -# "@npm//name-of-package" -# eg. "@npm//lodash" RUNTIME_DEPS = [ + "@npm//rxjs", ] -# In this array place dependencies necessary to build the types, which will include the -# :npm_module_types target of other packages and packages from NPM, including @types/* -# packages. -# -# To reference the types for another package use: -# "//repo/relative/path/to/package:npm_module_types" -# eg. "//packages/kbn-utils:npm_module_types" -# -# References to NPM packages work the same as RUNTIME_DEPS TYPES_DEPS = [ "@npm//@types/node", "@npm//@types/jest", - "//packages/kbn-jsonc:npm_module_types", + "@npm//rxjs", + "//packages/kbn-utility-types:npm_module_types", + "//packages/core/base/core-base-common:npm_module_types", + "//packages/core/status/core-status-server:npm_module_types", + "//packages/core/status/core-status-server-internal:npm_module_types", ] jsts_transpiler( @@ -86,7 +70,6 @@ ts_project( deps = TYPES_DEPS, declaration = True, declaration_map = True, - allow_js = True, emit_declaration_only = True, out_dir = "target_types", tsconfig = ":tsconfig", diff --git a/packages/core/status/core-status-server-mocks/README.md b/packages/core/status/core-status-server-mocks/README.md new file mode 100644 index 00000000000000..1505430a6c7197 --- /dev/null +++ b/packages/core/status/core-status-server-mocks/README.md @@ -0,0 +1,4 @@ +# @kbn/core-status-server-mocks + +This package contains mocks types for Core's server-side `status` service. +- `statusServiceMock` \ No newline at end of file diff --git a/packages/core/status/core-status-server-mocks/index.ts b/packages/core/status/core-status-server-mocks/index.ts new file mode 100644 index 00000000000000..581214f5ddb0c5 --- /dev/null +++ b/packages/core/status/core-status-server-mocks/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export { statusServiceMock } from './src'; diff --git a/packages/kbn-kibana-manifest-parser/jest.config.js b/packages/core/status/core-status-server-mocks/jest.config.js similarity index 81% rename from packages/kbn-kibana-manifest-parser/jest.config.js rename to packages/core/status/core-status-server-mocks/jest.config.js index f50552e3e36e5a..02beffdf16678c 100644 --- a/packages/kbn-kibana-manifest-parser/jest.config.js +++ b/packages/core/status/core-status-server-mocks/jest.config.js @@ -8,6 +8,6 @@ module.exports = { preset: '@kbn/test/jest_node', - rootDir: '../..', - roots: ['/packages/kbn-kibana-manifest-parser'], + rootDir: '../../../..', + roots: ['/packages/core/status/core-status-server-mocks'], }; diff --git a/packages/core/status/core-status-server-mocks/kibana.jsonc b/packages/core/status/core-status-server-mocks/kibana.jsonc new file mode 100644 index 00000000000000..04f0e29eedf726 --- /dev/null +++ b/packages/core/status/core-status-server-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-status-server-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-kibana-manifest-parser/package.json b/packages/core/status/core-status-server-mocks/package.json similarity index 64% rename from packages/kbn-kibana-manifest-parser/package.json rename to packages/core/status/core-status-server-mocks/package.json index e2ab7ac2417e98..406cc5eae71aa8 100644 --- a/packages/kbn-kibana-manifest-parser/package.json +++ b/packages/core/status/core-status-server-mocks/package.json @@ -1,7 +1,8 @@ { - "name": "@kbn/kibana-manifest-parser", + "name": "@kbn/core-status-server-mocks", "private": true, "version": "1.0.0", "main": "./target_node/index.js", + "author": "Kibana Core", "license": "SSPL-1.0 OR Elastic License 2.0" } diff --git a/packages/core/status/core-status-server-mocks/src/index.ts b/packages/core/status/core-status-server-mocks/src/index.ts new file mode 100644 index 00000000000000..1b2913d19aa50e --- /dev/null +++ b/packages/core/status/core-status-server-mocks/src/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export { statusServiceMock } from './status_service.mock'; diff --git a/src/core/server/status/status_service.mock.ts b/packages/core/status/core-status-server-mocks/src/status_service.mock.ts similarity index 88% rename from src/core/server/status/status_service.mock.ts rename to packages/core/status/core-status-server-mocks/src/status_service.mock.ts index 7241bb2f0479e6..824b853b342fc8 100644 --- a/src/core/server/status/status_service.mock.ts +++ b/packages/core/status/core-status-server-mocks/src/status_service.mock.ts @@ -6,16 +6,11 @@ * Side Public License, v 1. */ -import type { PublicMethodsOf } from '@kbn/utility-types'; -import type { StatusService } from './status_service'; -import { - InternalStatusServiceSetup, - StatusServiceSetup, - ServiceStatusLevels, - ServiceStatus, - CoreStatus, -} from './types'; import { BehaviorSubject } from 'rxjs'; +import type { PublicMethodsOf } from '@kbn/utility-types'; +import { ServiceStatusLevels, ServiceStatus } from '@kbn/core-status-common'; +import type { StatusService, InternalStatusServiceSetup } from '@kbn/core-status-server-internal'; +import type { StatusServiceSetup, CoreStatus } from '@kbn/core-status-server'; const available: ServiceStatus = { level: ServiceStatusLevels.available, diff --git a/packages/core/status/core-status-server-mocks/tsconfig.json b/packages/core/status/core-status-server-mocks/tsconfig.json new file mode 100644 index 00000000000000..71bb40fe57f3f4 --- /dev/null +++ b/packages/core/status/core-status-server-mocks/tsconfig.json @@ -0,0 +1,17 @@ +{ + "extends": "../../../../tsconfig.bazel.json", + "compilerOptions": { + "declaration": true, + "declarationMap": true, + "emitDeclarationOnly": true, + "outDir": "target_types", + "stripInternal": false, + "types": [ + "jest", + "node" + ] + }, + "include": [ + "**/*.ts", + ] +} diff --git a/packages/kbn-jsonc/BUILD.bazel b/packages/core/status/core-status-server/BUILD.bazel similarity index 68% rename from packages/kbn-jsonc/BUILD.bazel rename to packages/core/status/core-status-server/BUILD.bazel index e38170649a9a8a..e48b21c23dc2fa 100644 --- a/packages/kbn-jsonc/BUILD.bazel +++ b/packages/core/status/core-status-server/BUILD.bazel @@ -2,12 +2,12 @@ load("@npm//@bazel/typescript:index.bzl", "ts_config") load("@build_bazel_rules_nodejs//:index.bzl", "js_library") load("//src/dev/bazel:index.bzl", "jsts_transpiler", "pkg_npm", "pkg_npm_types", "ts_project") -PKG_DIRNAME = "kbn-jsonc" -PKG_REQUIRE_NAME = "@kbn/jsonc" +PKG_DIRNAME = "core-status-server" +PKG_REQUIRE_NAME = "@kbn/core-status-server" SOURCE_FILES = glob( [ - "**/*.js", + "**/*.ts", ], exclude = [ "**/*.config.js", @@ -35,31 +35,15 @@ NPM_MODULE_EXTRA_FILES = [ "package.json", ] -# In this array place runtime dependencies, including other packages and NPM packages -# which must be available for this code to run. -# -# To reference other packages use: -# "//repo/relative/path/to/package" -# eg. "//packages/kbn-utils" -# -# To reference a NPM package use: -# "@npm//name-of-package" -# eg. "@npm//lodash" RUNTIME_DEPS = [ + "//packages/core/status/core-status-common", ] -# In this array place dependencies necessary to build the types, which will include the -# :npm_module_types target of other packages and packages from NPM, including @types/* -# packages. -# -# To reference the types for another package use: -# "//repo/relative/path/to/package:npm_module_types" -# eg. "//packages/kbn-utils:npm_module_types" -# -# References to NPM packages work the same as RUNTIME_DEPS TYPES_DEPS = [ "@npm//@types/node", "@npm//@types/jest", + "@npm//rxjs", + "//packages/core/status/core-status-common:npm_module_types", ] jsts_transpiler( @@ -84,7 +68,6 @@ ts_project( deps = TYPES_DEPS, declaration = True, declaration_map = True, - allow_js = True, emit_declaration_only = True, out_dir = "target_types", tsconfig = ":tsconfig", diff --git a/packages/core/status/core-status-server/README.md b/packages/core/status/core-status-server/README.md new file mode 100644 index 00000000000000..056512bf030801 --- /dev/null +++ b/packages/core/status/core-status-server/README.md @@ -0,0 +1,3 @@ +# @kbn/core-status-server + +This package contains the public types for Core's server-side `status` service. diff --git a/packages/core/status/core-status-server/index.ts b/packages/core/status/core-status-server/index.ts new file mode 100644 index 00000000000000..69e36d4f503c08 --- /dev/null +++ b/packages/core/status/core-status-server/index.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 + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export type { + ServiceStatusLevel, + ServiceStatus, + CoreStatus, + ServiceStatusLevelId, +} from '@kbn/core-status-common'; +export { ServiceStatusLevels } from '@kbn/core-status-common'; +export type { StatusServiceSetup } from './src'; diff --git a/packages/kbn-jsonc/jest.config.js b/packages/core/status/core-status-server/jest.config.js similarity index 82% rename from packages/kbn-jsonc/jest.config.js rename to packages/core/status/core-status-server/jest.config.js index c958647e1c1542..ca1edb6516461a 100644 --- a/packages/kbn-jsonc/jest.config.js +++ b/packages/core/status/core-status-server/jest.config.js @@ -8,6 +8,6 @@ module.exports = { preset: '@kbn/test/jest_node', - rootDir: '../..', - roots: ['/packages/kbn-jsonc'], + rootDir: '../../../..', + roots: ['/packages/core/status/core-status-server'], }; diff --git a/packages/core/status/core-status-server/kibana.jsonc b/packages/core/status/core-status-server/kibana.jsonc new file mode 100644 index 00000000000000..3021a52ce4c177 --- /dev/null +++ b/packages/core/status/core-status-server/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-status-server", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-jsonc/package.json b/packages/core/status/core-status-server/package.json similarity index 66% rename from packages/kbn-jsonc/package.json rename to packages/core/status/core-status-server/package.json index 73fc5acfe447c2..93dd8920d03a71 100644 --- a/packages/kbn-jsonc/package.json +++ b/packages/core/status/core-status-server/package.json @@ -1,7 +1,8 @@ { - "name": "@kbn/jsonc", + "name": "@kbn/core-status-server", "private": true, "version": "1.0.0", "main": "./target_node/index.js", + "author": "Kibana Core", "license": "SSPL-1.0 OR Elastic License 2.0" } diff --git a/src/core/server/status/types.ts b/packages/core/status/core-status-server/src/contracts.ts similarity index 78% rename from src/core/server/status/types.ts rename to packages/core/status/core-status-server/src/contracts.ts index 8217b29463700c..9e4b2613059503 100644 --- a/src/core/server/status/types.ts +++ b/packages/core/status/core-status-server/src/contracts.ts @@ -6,25 +6,8 @@ * Side Public License, v 1. */ -import { Observable } from 'rxjs'; -import type { PluginName, ServiceStatus } from '@kbn/core-base-common'; - -export type { ServiceStatusLevel, ServiceStatus } from '@kbn/core-base-common'; -export { ServiceStatusLevels } from '@kbn/core-base-common'; - -/** - * Status of core services. - * - * @internalRemarks - * Only contains entries for backend services that could have a non-available `status`. - * For example, `context` cannot possibly be broken, so it is not included. - * - * @public - */ -export interface CoreStatus { - elasticsearch: ServiceStatus; - savedObjects: ServiceStatus; -} +import type { Observable } from 'rxjs'; +import type { ServiceStatus, CoreStatus } from '@kbn/core-status-common'; /** * API for accessing status of Core and this plugin's dependencies as well as for customizing this plugin's status. @@ -138,19 +121,3 @@ export interface StatusServiceSetup { */ isStatusPageAnonymous: () => boolean; } - -/** @internal */ -export interface InternalStatusServiceSetup - extends Pick { - /** - * Overall status of core's service. - */ - coreOverall$: Observable; - - // Namespaced under `plugins` key to improve clarity that these are APIs for plugins specifically. - plugins: { - set(plugin: PluginName, status$: Observable): void; - getDependenciesStatus$(plugin: PluginName): Observable>; - getDerivedStatus$(plugin: PluginName): Observable; - }; -} diff --git a/packages/core/status/core-status-server/src/index.ts b/packages/core/status/core-status-server/src/index.ts new file mode 100644 index 00000000000000..53c4a1d5e8c98b --- /dev/null +++ b/packages/core/status/core-status-server/src/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export type { StatusServiceSetup } from './contracts'; diff --git a/packages/core/status/core-status-server/tsconfig.json b/packages/core/status/core-status-server/tsconfig.json new file mode 100644 index 00000000000000..71bb40fe57f3f4 --- /dev/null +++ b/packages/core/status/core-status-server/tsconfig.json @@ -0,0 +1,17 @@ +{ + "extends": "../../../../tsconfig.bazel.json", + "compilerOptions": { + "declaration": true, + "declarationMap": true, + "emitDeclarationOnly": true, + "outDir": "target_types", + "stripInternal": false, + "types": [ + "jest", + "node" + ] + }, + "include": [ + "**/*.ts", + ] +} diff --git a/packages/core/test-helpers/core-test-helpers-deprecations-getters/kibana.jsonc b/packages/core/test-helpers/core-test-helpers-deprecations-getters/kibana.jsonc new file mode 100644 index 00000000000000..1c245768d3f7d4 --- /dev/null +++ b/packages/core/test-helpers/core-test-helpers-deprecations-getters/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-test-helpers-deprecations-getters", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/test-helpers/core-test-helpers-http-setup-browser/kibana.jsonc b/packages/core/test-helpers/core-test-helpers-http-setup-browser/kibana.jsonc new file mode 100644 index 00000000000000..f5e257dd883a5f --- /dev/null +++ b/packages/core/test-helpers/core-test-helpers-http-setup-browser/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-test-helpers-http-setup-browser", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/theme/core-theme-browser-internal/kibana.jsonc b/packages/core/theme/core-theme-browser-internal/kibana.jsonc new file mode 100644 index 00000000000000..36842b069548b8 --- /dev/null +++ b/packages/core/theme/core-theme-browser-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-theme-browser-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/theme/core-theme-browser-mocks/kibana.jsonc b/packages/core/theme/core-theme-browser-mocks/kibana.jsonc new file mode 100644 index 00000000000000..e46f0193c40681 --- /dev/null +++ b/packages/core/theme/core-theme-browser-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-theme-browser-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/theme/core-theme-browser/kibana.jsonc b/packages/core/theme/core-theme-browser/kibana.jsonc new file mode 100644 index 00000000000000..9dbe039d706408 --- /dev/null +++ b/packages/core/theme/core-theme-browser/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-theme-browser", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/ui-settings/core-ui-settings-browser-internal/kibana.jsonc b/packages/core/ui-settings/core-ui-settings-browser-internal/kibana.jsonc new file mode 100644 index 00000000000000..9a46e97ec89af6 --- /dev/null +++ b/packages/core/ui-settings/core-ui-settings-browser-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-ui-settings-browser-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/ui-settings/core-ui-settings-browser-mocks/kibana.jsonc b/packages/core/ui-settings/core-ui-settings-browser-mocks/kibana.jsonc new file mode 100644 index 00000000000000..f6906835b648fb --- /dev/null +++ b/packages/core/ui-settings/core-ui-settings-browser-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-ui-settings-browser-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/ui-settings/core-ui-settings-browser/kibana.jsonc b/packages/core/ui-settings/core-ui-settings-browser/kibana.jsonc new file mode 100644 index 00000000000000..9129ef435fb677 --- /dev/null +++ b/packages/core/ui-settings/core-ui-settings-browser/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-ui-settings-browser", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/ui-settings/core-ui-settings-common/kibana.jsonc b/packages/core/ui-settings/core-ui-settings-common/kibana.jsonc new file mode 100644 index 00000000000000..4d9b575423696f --- /dev/null +++ b/packages/core/ui-settings/core-ui-settings-common/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-ui-settings-common", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/usage-data/core-usage-data-base-server-internal/kibana.jsonc b/packages/core/usage-data/core-usage-data-base-server-internal/kibana.jsonc new file mode 100644 index 00000000000000..d35d6c2bbd6d75 --- /dev/null +++ b/packages/core/usage-data/core-usage-data-base-server-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-usage-data-base-server-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/usage-data/core-usage-data-server-internal/kibana.jsonc b/packages/core/usage-data/core-usage-data-server-internal/kibana.jsonc new file mode 100644 index 00000000000000..30bf6865b5bb4a --- /dev/null +++ b/packages/core/usage-data/core-usage-data-server-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-usage-data-server-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/usage-data/core-usage-data-server-mocks/kibana.jsonc b/packages/core/usage-data/core-usage-data-server-mocks/kibana.jsonc new file mode 100644 index 00000000000000..f12bd25bee867f --- /dev/null +++ b/packages/core/usage-data/core-usage-data-server-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-usage-data-server-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/usage-data/core-usage-data-server/kibana.jsonc b/packages/core/usage-data/core-usage-data-server/kibana.jsonc new file mode 100644 index 00000000000000..a785db80907130 --- /dev/null +++ b/packages/core/usage-data/core-usage-data-server/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-usage-data-server", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/home/sample_data_card/kibana.jsonc b/packages/home/sample_data_card/kibana.jsonc new file mode 100644 index 00000000000000..2dd9813151b2c0 --- /dev/null +++ b/packages/home/sample_data_card/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/home-sample-data-card", + "owner": "@elastic/shared-ux", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/home/sample_data_tab/kibana.jsonc b/packages/home/sample_data_tab/kibana.jsonc new file mode 100644 index 00000000000000..d734b947444a93 --- /dev/null +++ b/packages/home/sample_data_tab/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/home-sample-data-tab", + "owner": "@elastic/shared-ux", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/home/sample_data_types/kibana.jsonc b/packages/home/sample_data_types/kibana.jsonc new file mode 100644 index 00000000000000..9b7458fe54946c --- /dev/null +++ b/packages/home/sample_data_types/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/home-sample-data-types", + "owner": "@elastic/shared-ux", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-ace/kibana.jsonc b/packages/kbn-ace/kibana.jsonc new file mode 100644 index 00000000000000..25da4fe177ee2c --- /dev/null +++ b/packages/kbn-ace/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/ace", + "owner": "@elastic/platform-deployment-management", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-alerts/kibana.jsonc b/packages/kbn-alerts/kibana.jsonc new file mode 100644 index 00000000000000..93b42c4ef86bf3 --- /dev/null +++ b/packages/kbn-alerts/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/alerts", + "owner": "@elastic/security-solution", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-ambient-storybook-types/kibana.jsonc b/packages/kbn-ambient-storybook-types/kibana.jsonc new file mode 100644 index 00000000000000..d04a5a93e29600 --- /dev/null +++ b/packages/kbn-ambient-storybook-types/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/ambient-storybook-types", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-ambient-storybook-types/package.json b/packages/kbn-ambient-storybook-types/package.json index 301d28d5e585ce..9a29b8f60ccd10 100644 --- a/packages/kbn-ambient-storybook-types/package.json +++ b/packages/kbn-ambient-storybook-types/package.json @@ -2,8 +2,5 @@ "name": "@kbn/ambient-storybook-types", "private": true, "version": "1.0.0", - "license": "SSPL-1.0 OR Elastic License 2.0", - "kibana": { - "devOnly": true - } + "license": "SSPL-1.0 OR Elastic License 2.0" } diff --git a/packages/kbn-ambient-ui-types/kibana.jsonc b/packages/kbn-ambient-ui-types/kibana.jsonc new file mode 100644 index 00000000000000..1837bcfbd5619b --- /dev/null +++ b/packages/kbn-ambient-ui-types/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/ambient-ui-types", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-ambient-ui-types/package.json b/packages/kbn-ambient-ui-types/package.json index ddeb5082cb41f3..9ff278bf1dbe22 100644 --- a/packages/kbn-ambient-ui-types/package.json +++ b/packages/kbn-ambient-ui-types/package.json @@ -2,8 +2,5 @@ "name": "@kbn/ambient-ui-types", "private": true, "version": "1.0.0", - "license": "SSPL-1.0 OR Elastic License 2.0", - "kibana": { - "devOnly": true - } + "license": "SSPL-1.0 OR Elastic License 2.0" } \ No newline at end of file diff --git a/packages/kbn-analytics/kibana.jsonc b/packages/kbn-analytics/kibana.jsonc new file mode 100644 index 00000000000000..06320d851340bf --- /dev/null +++ b/packages/kbn-analytics/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/analytics", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-apm-config-loader/kibana.jsonc b/packages/kbn-apm-config-loader/kibana.jsonc new file mode 100644 index 00000000000000..d817476c0b6dba --- /dev/null +++ b/packages/kbn-apm-config-loader/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/apm-config-loader", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-apm-synthtrace/kibana.jsonc b/packages/kbn-apm-synthtrace/kibana.jsonc new file mode 100644 index 00000000000000..0bde4f9d7715ae --- /dev/null +++ b/packages/kbn-apm-synthtrace/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/apm-synthtrace", + "devOnly": true, + "owner": "@elastic/apm-ui", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-apm-utils/kibana.jsonc b/packages/kbn-apm-utils/kibana.jsonc new file mode 100644 index 00000000000000..3db7022ea44c54 --- /dev/null +++ b/packages/kbn-apm-utils/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/apm-utils", + "owner": "@elastic/apm-ui", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-axe-config/kibana.jsonc b/packages/kbn-axe-config/kibana.jsonc new file mode 100644 index 00000000000000..f2444755f90967 --- /dev/null +++ b/packages/kbn-axe-config/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/axe-config", + "devOnly": true, + "owner": "@elastic/kibana-qa", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-axe-config/package.json b/packages/kbn-axe-config/package.json index c5b929478c3de7..62dd325c3ca2fd 100644 --- a/packages/kbn-axe-config/package.json +++ b/packages/kbn-axe-config/package.json @@ -4,8 +4,5 @@ "version": "1.0.0", "main": "./target_node/index.js", "browser": "./target_web/index.js", - "license": "SSPL-1.0 OR Elastic License 2.0", - "kibana": { - "devOnly": true - } + "license": "SSPL-1.0 OR Elastic License 2.0" } diff --git a/packages/kbn-babel-plugin-synthetic-packages/kibana.jsonc b/packages/kbn-babel-plugin-synthetic-packages/kibana.jsonc new file mode 100644 index 00000000000000..a426d7bec6a2bf --- /dev/null +++ b/packages/kbn-babel-plugin-synthetic-packages/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/babel-plugin-synthetic-packages", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-babel-plugin-synthetic-packages/package.json b/packages/kbn-babel-plugin-synthetic-packages/package.json index f488064fc6100e..89de157a117242 100644 --- a/packages/kbn-babel-plugin-synthetic-packages/package.json +++ b/packages/kbn-babel-plugin-synthetic-packages/package.json @@ -3,8 +3,5 @@ "private": true, "version": "1.0.0", "main": "./babel_plugin_synthetic_packages.js", - "license": "SSPL-1.0 OR Elastic License 2.0", - "kibana": { - "devOnly": true - } + "license": "SSPL-1.0 OR Elastic License 2.0" } diff --git a/packages/kbn-babel-preset/kibana.jsonc b/packages/kbn-babel-preset/kibana.jsonc new file mode 100644 index 00000000000000..fa4ca725c56de6 --- /dev/null +++ b/packages/kbn-babel-preset/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/babel-preset", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-babel-preset/package.json b/packages/kbn-babel-preset/package.json index e0b90d9e41ccd1..1ff04ec1df1228 100644 --- a/packages/kbn-babel-preset/package.json +++ b/packages/kbn-babel-preset/package.json @@ -2,8 +2,5 @@ "name": "@kbn/babel-preset", "version": "1.0.0", "private": true, - "license": "SSPL-1.0 OR Elastic License 2.0", - "kibana": { - "devOnly": true - } + "license": "SSPL-1.0 OR Elastic License 2.0" } diff --git a/packages/kbn-bazel-packages/index.js b/packages/kbn-bazel-packages/index.js index da3e620e14ef90..5849bd151c8ea0 100644 --- a/packages/kbn-bazel-packages/index.js +++ b/packages/kbn-bazel-packages/index.js @@ -7,13 +7,26 @@ */ /** @typedef {import('./src/bazel_package').BazelPackage} BazelPackage */ +/** @typedef {import('./src/types').KibanaPackageManifest} KibanaPackageManifest */ +/** @typedef {import('./src/types').KibanaPackageType} KibanaPackageType */ +/** @typedef {import('./src/types').ParsedPackageJson} ParsedPackageJson */ const { BAZEL_PACKAGE_DIRS, getAllBazelPackageDirs } = require('./src/bazel_package_dirs'); -const { discoverBazelPackageLocations, discoverBazelPackages } = require('./src/discover_packages'); +const { discoverPackageManifestPaths, discoverBazelPackages } = require('./src/discover_packages'); +const { + parsePackageManifest, + readPackageManifest, + validatePackageManifest, +} = require('./src/parse_package_manifest'); +const Jsonc = require('./src/jsonc'); module.exports = { BAZEL_PACKAGE_DIRS, getAllBazelPackageDirs, - discoverBazelPackageLocations, + discoverPackageManifestPaths, discoverBazelPackages, + parsePackageManifest, + readPackageManifest, + validatePackageManifest, + Jsonc, }; diff --git a/packages/kbn-bazel-packages/kibana.jsonc b/packages/kbn-bazel-packages/kibana.jsonc new file mode 100644 index 00000000000000..fc373ccad73adb --- /dev/null +++ b/packages/kbn-bazel-packages/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/bazel-packages", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-bazel-packages/package.json b/packages/kbn-bazel-packages/package.json index 085f0bb4510f0f..fabf8b6cbbc14c 100644 --- a/packages/kbn-bazel-packages/package.json +++ b/packages/kbn-bazel-packages/package.json @@ -3,8 +3,5 @@ "private": true, "version": "1.0.0", "main": "./target_node/index.js", - "license": "SSPL-1.0 OR Elastic License 2.0", - "kibana": { - "devOnly": true - } + "license": "SSPL-1.0 OR Elastic License 2.0" } diff --git a/packages/kbn-bazel-packages/src/bazel_package.js b/packages/kbn-bazel-packages/src/bazel_package.js index c6a31ccc0dbc1f..4a6d1b69bd8b2f 100644 --- a/packages/kbn-bazel-packages/src/bazel_package.js +++ b/packages/kbn-bazel-packages/src/bazel_package.js @@ -10,8 +10,8 @@ const { inspect } = require('util'); const Path = require('path'); const Fsp = require('fs/promises'); -/** @typedef {import('./types').ParsedPackageJson} ParsedPackageJson */ const { readPackageJson } = require('./parse_package_json'); +const { readPackageManifest } = require('./parse_package_manifest'); const BUILD_RULE_NAME = /(^|\s)name\s*=\s*"build"/; const BUILD_TYPES_RULE_NAME = /(^|\s)name\s*=\s*"build_types"/; @@ -20,7 +20,8 @@ const BUILD_TYPES_RULE_NAME = /(^|\s)name\s*=\s*"build_types"/; * Representation of a Bazel Package in the Kibana repository * @class * @property {string} normalizedRepoRelativeDir - * @property {import('./types').ParsedPackageJson} pkg + * @property {import('./types').KibanaPackageManifest} manifest + * @property {import('./types').ParsedPackageJson | undefined} pkg * @property {string | undefined} buildBazelContent */ class BazelPackage { @@ -28,10 +29,11 @@ class BazelPackage { * Create a BazelPackage object from a package directory. Reads some files from the package and returns * a Promise for a BazelPackage instance. * @param {string} repoRoot - * @param {string} dir + * @param {string} path */ - static async fromDir(repoRoot, dir) { - const pkg = readPackageJson(Path.resolve(dir, 'package.json')); + static async fromManifest(repoRoot, path) { + const manifest = readPackageManifest(path); + const dir = Path.dirname(path); let buildBazelContent; try { @@ -40,7 +42,29 @@ class BazelPackage { throw new Error(`unable to read BUILD.bazel file in [${dir}]: ${error.message}`); } - return new BazelPackage(Path.relative(repoRoot, dir), pkg, buildBazelContent); + return new BazelPackage( + Path.relative(repoRoot, dir), + manifest, + readPackageJson(Path.resolve(dir, 'package.json')), + buildBazelContent + ); + } + + /** + * Sort a list of bazek packages + * @param {BazelPackage[]} pkgs + */ + static sort(pkgs) { + return pkgs.slice().sort(BazelPackage.sorter); + } + + /** + * Sort an array of bazel packages + * @param {BazelPackage} a + * @param {BazelPackage} b + */ + static sorter(a, b) { + return a.normalizedRepoRelativeDir.localeCompare(b.normalizedRepoRelativeDir); } constructor( @@ -49,9 +73,14 @@ class BazelPackage { * @type {string} */ normalizedRepoRelativeDir, + /** + * Parsed kibana.jsonc manifest from the package + * @type {import('./types').KibanaPackageManifest} + */ + manifest, /** * Parsed package.json file from the package - * @type {import('./types').ParsedPackageJson} + * @type {import('./types').ParsedPackageJson | undefined} */ pkg, /** @@ -61,6 +90,7 @@ class BazelPackage { buildBazelContent = undefined ) { this.normalizedRepoRelativeDir = normalizedRepoRelativeDir; + this.manifest = manifest; this.pkg = pkg; this.buildBazelContent = buildBazelContent; } @@ -83,7 +113,7 @@ class BazelPackage { * Returns true if the package is not intended to be in the build */ isDevOnly() { - return !!this.pkg.kibana?.devOnly; + return !!this.manifest.devOnly; } /** diff --git a/packages/kbn-bazel-packages/src/bazel_package.test.ts b/packages/kbn-bazel-packages/src/bazel_package.test.ts index 70d540e43f06af..16a06dab7e08e3 100644 --- a/packages/kbn-bazel-packages/src/bazel_package.test.ts +++ b/packages/kbn-bazel-packages/src/bazel_package.test.ts @@ -10,39 +10,51 @@ import Fs from 'fs'; import Path from 'path'; import { BazelPackage } from './bazel_package'; +import { KibanaPackageManifest, ParsedPackageJson } from './types'; const OWN_BAZEL_BUILD_FILE = Fs.readFileSync(Path.resolve(__dirname, '../BUILD.bazel'), 'utf8'); +const pkgJson: ParsedPackageJson = { + name: 'foo', +}; +const manifest: KibanaPackageManifest = { + type: 'shared-common', + id: '@kbn/foo', + owner: '@elastic/kibana-operations', + runtimeDeps: [], + typeDeps: [], +}; + describe('hasBuildRule()', () => { it('returns true if there is a rule with the name "build"', () => { - const pkg = new BazelPackage('foo', { name: 'foo' }, OWN_BAZEL_BUILD_FILE); + const pkg = new BazelPackage('foo', manifest, pkgJson, OWN_BAZEL_BUILD_FILE); expect(pkg.hasBuildRule()).toBe(true); }); it('returns false if there is no rule with name "build"', () => { - const pkg = new BazelPackage('foo', { name: 'foo' }, ``); + const pkg = new BazelPackage('foo', manifest, pkgJson, ``); expect(pkg.hasBuildRule()).toBe(false); }); it('returns false if there is no BUILD.bazel file', () => { - const pkg = new BazelPackage('foo', { name: 'foo' }); + const pkg = new BazelPackage('foo', manifest, pkgJson); expect(pkg.hasBuildRule()).toBe(false); }); }); describe('hasBuildTypesRule()', () => { it('returns true if there is a rule with the name "build_types"', () => { - const pkg = new BazelPackage('foo', { name: 'foo' }, OWN_BAZEL_BUILD_FILE); + const pkg = new BazelPackage('foo', manifest, pkgJson, OWN_BAZEL_BUILD_FILE); expect(pkg.hasBuildTypesRule()).toBe(true); }); it('returns false if there is no rule with name "build_types"', () => { - const pkg = new BazelPackage('foo', { name: 'foo' }, ``); + const pkg = new BazelPackage('foo', manifest, pkgJson, ``); expect(pkg.hasBuildTypesRule()).toBe(false); }); it('returns false if there is no BUILD.bazel file', () => { - const pkg = new BazelPackage('foo', { name: 'foo' }); + const pkg = new BazelPackage('foo', manifest, pkgJson); expect(pkg.hasBuildTypesRule()).toBe(false); }); }); diff --git a/packages/kbn-bazel-packages/src/discover_packages.js b/packages/kbn-bazel-packages/src/discover_packages.js index 17678115c74526..5532205404d26e 100644 --- a/packages/kbn-bazel-packages/src/discover_packages.js +++ b/packages/kbn-bazel-packages/src/discover_packages.js @@ -6,39 +6,34 @@ * Side Public License, v 1. */ -const Path = require('path'); - const { BazelPackage } = require('./bazel_package'); const { getAllBazelPackageDirs } = require('./bazel_package_dirs'); const { findPackages } = require('./find_files'); const { asyncMapWithLimit } = require('./async'); /** + * Returns an array of all the package manifest paths in the repository * @param {string} repoRoot */ -function discoverBazelPackageLocations(repoRoot) { - const packagesWithBuildBazel = getAllBazelPackageDirs(repoRoot) - .flatMap((packageDir) => findPackages(packageDir, 'BUILD.bazel')) - .map((path) => Path.dirname(path)); - - // NOTE: only return as discovered packages with a package.json + BUILD.bazel file. - // In the future we should change this to only discover the ones with kibana.jsonc. +function discoverPackageManifestPaths(repoRoot) { return getAllBazelPackageDirs(repoRoot) - .flatMap((packageDir) => findPackages(packageDir, 'package.json')) - .map((path) => Path.dirname(path)) - .filter((pkg) => packagesWithBuildBazel.includes(pkg)) + .flatMap((packageDir) => findPackages(packageDir, 'kibana.jsonc')) .sort((a, b) => a.localeCompare(b)); } /** + * Resolves to an array of BazelPackage instances which parse the manifest files, + * package.json files, and provide useful metadata about each package. * @param {string} repoRoot */ async function discoverBazelPackages(repoRoot) { - return await asyncMapWithLimit( - discoverBazelPackageLocations(repoRoot), - 100, - async (dir) => await BazelPackage.fromDir(repoRoot, dir) + return BazelPackage.sort( + await asyncMapWithLimit( + discoverPackageManifestPaths(repoRoot), + 100, + async (path) => await BazelPackage.fromManifest(repoRoot, path) + ) ); } -module.exports = { discoverBazelPackageLocations, discoverBazelPackages }; +module.exports = { discoverPackageManifestPaths, discoverBazelPackages }; diff --git a/packages/kbn-jsonc/index.js b/packages/kbn-bazel-packages/src/jsonc.js similarity index 87% rename from packages/kbn-jsonc/index.js rename to packages/kbn-bazel-packages/src/jsonc.js index 4788833f0f4d7a..54d43b2e666d80 100644 --- a/packages/kbn-jsonc/index.js +++ b/packages/kbn-bazel-packages/src/jsonc.js @@ -6,10 +6,11 @@ * Side Public License, v 1. */ -const { stripJsonComments } = require('./src/strip_json_comments'); +const { stripJsonComments } = require('./strip_json_comments'); /** * @param {string} jsonWithComments + * @returns {unknown} */ function parse(jsonWithComments) { return JSON.parse( diff --git a/packages/kbn-bazel-packages/src/parse_package_json.js b/packages/kbn-bazel-packages/src/parse_package_json.js index 27a78f91a44661..adcf176ea6853f 100644 --- a/packages/kbn-bazel-packages/src/parse_package_json.js +++ b/packages/kbn-bazel-packages/src/parse_package_json.js @@ -22,8 +22,12 @@ function isObj(v) { * @returns {asserts v is import('./types').ParsedPackageJson} */ function validateParsedPackageJson(v) { - if (!isObj(v) || typeof v.name !== 'string') { - throw new Error('Expected at least a "name" property'); + if (!isObj(v)) { + throw new Error('Expected package.json to be a JSON object'); + } + + if (typeof v.name !== 'string') { + throw new Error('Expected package.json to have a "name"'); } if (v.dependencies && !isObj(v.dependencies)) { @@ -49,7 +53,7 @@ function validateParsedPackageJson(v) { /** * Reads a given package.json file from disk and parses it * @param {string} path - * @returns {import('./types').ParsedPackageJson} + * @returns {import('./types').ParsedPackageJson | undefined} */ function readPackageJson(path) { let pkg; @@ -57,7 +61,9 @@ function readPackageJson(path) { pkg = JSON.parse(Fs.readFileSync(path, 'utf8')); validateParsedPackageJson(pkg); } catch (error) { - throw new Error(`unable to parse package.json at [${path}]: ${error.message}`); + if (error.code !== 'ENOENT') { + throw new Error(`unable to parse package.json at [${path}]: ${error.message}`); + } } return pkg; } diff --git a/packages/kbn-bazel-packages/src/parse_package_manifest.js b/packages/kbn-bazel-packages/src/parse_package_manifest.js new file mode 100644 index 00000000000000..42acbf3e603664 --- /dev/null +++ b/packages/kbn-bazel-packages/src/parse_package_manifest.js @@ -0,0 +1,225 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +const Fs = require('fs'); +const { inspect } = require('util'); + +const { + isObj, + isValidId, + isValidPkgType, + isArrOfIds, + isArrOfStrings, + PACKAGE_TYPES, +} = require('./parse_utils'); +const { parse } = require('./jsonc'); + +/** + * @param {string} key + * @param {unknown} value + * @param {string} msg + * @returns {Error} + */ +const err = (key, value, msg) => { + const dbg = ['string', 'number', 'boolean'].includes(typeof value) ? value : inspect(value); + return new Error(`invalid package "${key}" [${dbg}], ${msg}`); +}; + +/** + * @param {unknown} plugin + * @returns {import('./types').PluginPackageManifest['plugin']} + */ +function validatePackageManifestPlugin(plugin) { + if (!isObj(plugin)) { + throw err(`plugin`, plugin, `must be an object`); + } + + const { + id, + configPath, + requiredPlugins, + optionalPlugins, + description, + enabledOnAnonymousPages, + serviceFolders, + ...extra + } = plugin; + + const extraKeys = Object.keys(extra); + if (extraKeys.length) { + throw new Error(`unexpected keys in "plugin" of package [${extraKeys.join(', ')}]`); + } + + if (typeof id !== 'string' || !isValidId(id)) { + throw err(`plugin.id`, id, `must be a string in camel or snake case`); + } + + if (configPath !== undefined && !isArrOfIds(configPath)) { + throw err( + `plugin.configPath`, + configPath, + `must be an array of strings in camel or snake case` + ); + } + + if (requiredPlugins !== undefined && !isArrOfIds(requiredPlugins)) { + throw err( + `plugin.requiredPlugins`, + requiredPlugins, + `must be an array of strings in camel or snake case` + ); + } + + if (optionalPlugins !== undefined && !isArrOfIds(optionalPlugins)) { + throw err( + `plugin.requiredPlugins`, + optionalPlugins, + `must be an array of strings in camel or snake case` + ); + } + + if (description !== undefined && typeof description !== 'string') { + throw err(`plugin.description`, description, `must be a string`); + } + + if (enabledOnAnonymousPages !== undefined && typeof enabledOnAnonymousPages !== 'boolean') { + throw err(`plugin.enabledOnAnonymousPages`, enabledOnAnonymousPages, `must be a boolean`); + } + + if (serviceFolders !== undefined && !isArrOfStrings(serviceFolders)) { + throw err(`plugin.serviceFolders`, serviceFolders, `must be an array of strings`); + } + + return { + id, + configPath, + requiredPlugins, + optionalPlugins, + description, + enabledOnAnonymousPages, + serviceFolders, + }; +} + +/** + * Validate the contents of a parsed kibana.jsonc file. + * @param {unknown} parsed + * @returns {import('./types').KibanaPackageManifest} + */ +function validatePackageManifest(parsed) { + if (!isObj(parsed)) { + throw new Error('expected manifest root to be an object'); + } + + const { type, id, owner, typeDeps, runtimeDeps, devOnly, plugin, sharedBrowserBundle, ...extra } = + parsed; + + const extraKeys = Object.keys(extra); + if (extraKeys.length) { + throw new Error(`unexpected keys in package manifest [${extraKeys.join(', ')}]`); + } + + if (!isValidPkgType(type)) { + throw err(`type`, type, `options are [${PACKAGE_TYPES.join(', ')}]`); + } + + if (typeof id !== 'string' || !id.startsWith('@kbn/')) { + throw err(`id`, id, `must be a string that starts with @kbn/`); + } + + if (typeof owner !== 'string' || !owner.startsWith('@')) { + throw err(`owner`, owner, `must be a valid Github team handle starting with @`); + } + + if (!isArrOfStrings(typeDeps)) { + throw err(`typeDeps`, typeDeps, `must be an array of strings`); + } + + if (!isArrOfStrings(runtimeDeps)) { + throw err(`runtimeDeps`, runtimeDeps, `must be an array of strings`); + } + + if (devOnly !== undefined && typeof devOnly !== 'boolean') { + throw err(`devOnly`, devOnly, `must be a boolean when defined`); + } + + const base = { + id, + owner, + typeDeps, + runtimeDeps, + devOnly, + }; + + // return if this is one of the more basic types of package types + if (type === 'shared-server' || type === 'functional-tests' || type === 'test-helper') { + return { + type, + ...base, + }; + } + + // handle the plugin field for plugin-* types + if (type === 'plugin-browser' || type === 'plugin-server') { + return { + type, + ...base, + plugin: validatePackageManifestPlugin(plugin), + }; + } + + // parse the sharedBrowserBundle for shared-browser and shared-common types + if (sharedBrowserBundle !== undefined && typeof sharedBrowserBundle !== 'boolean') { + throw err(`sharedBrowserBundle`, sharedBrowserBundle, `must be a boolean when defined`); + } + return { + type, + ...base, + sharedBrowserBundle, + }; +} + +/** + * Parse a kibana.jsonc file from the filesystem + * @param {string} path + */ +function readPackageManifest(path) { + let content; + try { + content = Fs.readFileSync(path, 'utf8'); + } catch (error) { + if (error.code === 'ENOENT') { + throw new Error(`Missing kibana.jsonc file at ${path}`); + } + + throw error; + } + + try { + return parsePackageManifest(content); + } catch (error) { + throw new Error(`Unable to parse [${path}]: ${error.message}`); + } +} + +/** + * Parse a kibana.jsonc file from a string + * @param {string} content + */ +function parsePackageManifest(content) { + let parsed; + try { + parsed = parse(content); + } catch (error) { + throw new Error(`Invalid JSONc: ${error.message}`); + } + + return validatePackageManifest(parsed); +} + +module.exports = { parsePackageManifest, readPackageManifest, validatePackageManifest }; diff --git a/packages/kbn-bazel-packages/src/parse_utils.js b/packages/kbn-bazel-packages/src/parse_utils.js new file mode 100644 index 00000000000000..639f5b2391580c --- /dev/null +++ b/packages/kbn-bazel-packages/src/parse_utils.js @@ -0,0 +1,71 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +/** @type {{ [k in import('./types').KibanaPackageType]: true }} */ +const PACKAGE_TYPE_MAP = { + 'functional-tests': true, + 'plugin-browser': true, + 'plugin-server': true, + 'shared-browser': true, + 'shared-common': true, + 'shared-scss': true, + 'shared-server': true, + 'test-helper': true, +}; + +const PACKAGE_TYPES = /** @type {Array} */ ( + /** @type {unknown} */ (Object.keys(PACKAGE_TYPE_MAP)) +); + +const ID_PATTERN = /^[a-z][a-zA-Z_]*$/; + +/** + * @param {unknown} v + * @returns {v is Record} + */ +function isObj(v) { + return typeof v === 'object' && v !== null; +} + +/** @param {unknown} v */ +function isValidId(v) { + return typeof v === 'string' && ID_PATTERN.test(v); +} + +/** + * @param {unknown} v + * @returns {v is import('./types').KibanaPackageType} + */ +function isValidPkgType(v) { + return typeof v === 'string' && Object.hasOwn(PACKAGE_TYPE_MAP, v); +} + +/** + * @param {unknown} v + * @returns {v is string[]} + */ +function isArrOfStrings(v) { + return Array.isArray(v) && v.every((i) => typeof i === 'string'); +} + +/** + * @param {unknown} v + * @returns {v is string[]} + */ +function isArrOfIds(v) { + return Array.isArray(v) && v.every(isValidId); +} + +module.exports = { + PACKAGE_TYPES, + isObj, + isValidId, + isValidPkgType, + isArrOfIds, + isArrOfStrings, +}; diff --git a/packages/kbn-jsonc/src/strip_json_comments.js b/packages/kbn-bazel-packages/src/strip_json_comments.js similarity index 100% rename from packages/kbn-jsonc/src/strip_json_comments.js rename to packages/kbn-bazel-packages/src/strip_json_comments.js diff --git a/packages/kbn-bazel-packages/src/types.ts b/packages/kbn-bazel-packages/src/types.ts index dc77d35bc206af..c4b445adfd851a 100644 --- a/packages/kbn-bazel-packages/src/types.ts +++ b/packages/kbn-bazel-packages/src/types.ts @@ -29,3 +29,87 @@ export interface ParsedPackageJson { /** All other fields in the package.json are typed as unknown as we don't care what they are */ [key: string]: unknown; } + +export type KibanaPackageType = + | 'plugin-browser' + | 'plugin-server' + | 'shared-browser' + | 'shared-server' + | 'shared-common' + | 'shared-scss' + | 'functional-tests' + | 'test-helper'; + +interface PackageManifestBaseFields { + /** + * The type of this package. Package types define how a package can and should + * be used/built. Some package types also change the way that packages are + * interpreted. + */ + type: KibanaPackageType; + /** + * Module ID for this package. This must be globbally unique amoungst all + * packages and should include the most important information about how this + * package should be used. Avoid generic names to aid in disambiguation. + */ + id: string; + /** + * Github handle for the person or team who is responsible for this package. + * This owner will be used in the codeowners files for this package. + * + * For additional codeowners, you add manually add entries to the codeowners file. + */ + owner: string; + /** + * Packages which are required for the source code in the package to be type- + * checked. This list is updated automatically by the package linter + */ + typeDeps: string[]; + /** + * Packages which are required for the source code of the package to run. This + * list is updated automatically by the package linter. + */ + runtimeDeps: string[]; + /** + * A devOnly package can be used by other devOnly packages (and only + * other devOnly packages) and will never be included in the distributable + */ + devOnly?: boolean; +} + +export interface PluginPackageManifest extends PackageManifestBaseFields { + type: 'plugin-browser' | 'plugin-server'; + /** + * Details about the plugin which is contained within this package. + */ + plugin: { + id: string; + configPath?: string[]; + requiredPlugins?: string[]; + optionalPlugins?: string[]; + description?: string; + enabledOnAnonymousPages?: boolean; + serviceFolders?: string[]; + }; +} + +export interface SharedBrowserPackageManifest extends PackageManifestBaseFields { + type: 'shared-browser' | 'shared-common'; + /** + * When a package is used by many other packages in the browser, or requires some + * specific state in the module scope (though we highly recommend against this) you + * can set `sharedBrowserBundle` to true so this package to load in a separate async + * bundle request rather than being copied into the bundles of each package which + * use it. (not yet implemented) + */ + sharedBrowserBundle?: boolean; +} + +export interface BasePackageManifest extends PackageManifestBaseFields { + type: 'shared-server' | 'functional-tests' | 'test-helper' | 'shared-scss'; +} + +export type KibanaPackageManifest = + | PluginPackageManifest + | SharedBrowserPackageManifest + | BasePackageManifest; diff --git a/packages/kbn-bazel-runner/kibana.jsonc b/packages/kbn-bazel-runner/kibana.jsonc new file mode 100644 index 00000000000000..b313e99f5b9cca --- /dev/null +++ b/packages/kbn-bazel-runner/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/bazel-runner", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-bazel-runner/package.json b/packages/kbn-bazel-runner/package.json index d8fe010f0e4c3e..540dfbac4a0371 100644 --- a/packages/kbn-bazel-runner/package.json +++ b/packages/kbn-bazel-runner/package.json @@ -3,8 +3,5 @@ "private": true, "version": "1.0.0", "main": "./target_node/index.js", - "license": "SSPL-1.0 OR Elastic License 2.0", - "kibana": { - "devOnly": true - } + "license": "SSPL-1.0 OR Elastic License 2.0" } diff --git a/packages/kbn-chart-icons/kibana.jsonc b/packages/kbn-chart-icons/kibana.jsonc new file mode 100644 index 00000000000000..1d1de945c95de2 --- /dev/null +++ b/packages/kbn-chart-icons/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/chart-icons", + "owner": "@elastic/kibana-vis-editors", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-ci-stats-core/kibana.jsonc b/packages/kbn-ci-stats-core/kibana.jsonc new file mode 100644 index 00000000000000..9140ec71ef9127 --- /dev/null +++ b/packages/kbn-ci-stats-core/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/ci-stats-core", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-ci-stats-core/package.json b/packages/kbn-ci-stats-core/package.json index d1141ec3c55a83..fc56e2e3213eae 100644 --- a/packages/kbn-ci-stats-core/package.json +++ b/packages/kbn-ci-stats-core/package.json @@ -3,8 +3,5 @@ "private": true, "version": "1.0.0", "main": "./target_node/index.js", - "license": "SSPL-1.0 OR Elastic License 2.0", - "kibana": { - "devOnly": true - } + "license": "SSPL-1.0 OR Elastic License 2.0" } diff --git a/packages/kbn-ci-stats-performance-metrics/kibana.jsonc b/packages/kbn-ci-stats-performance-metrics/kibana.jsonc new file mode 100644 index 00000000000000..3c4b4a440a98f1 --- /dev/null +++ b/packages/kbn-ci-stats-performance-metrics/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/ci-stats-performance-metrics", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-ci-stats-performance-metrics/package.json b/packages/kbn-ci-stats-performance-metrics/package.json index e8da3dcde3dca3..0801174ab4a027 100644 --- a/packages/kbn-ci-stats-performance-metrics/package.json +++ b/packages/kbn-ci-stats-performance-metrics/package.json @@ -3,8 +3,5 @@ "private": true, "version": "1.0.0", "main": "./target_node/index.js", - "license": "SSPL-1.0 OR Elastic License 2.0", - "kibana": { - "devOnly": true - } + "license": "SSPL-1.0 OR Elastic License 2.0" } diff --git a/packages/kbn-ci-stats-reporter/kibana.jsonc b/packages/kbn-ci-stats-reporter/kibana.jsonc new file mode 100644 index 00000000000000..9991f55a342f97 --- /dev/null +++ b/packages/kbn-ci-stats-reporter/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/ci-stats-reporter", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-ci-stats-reporter/package.json b/packages/kbn-ci-stats-reporter/package.json index 01743bced98d55..1393c08cddac4e 100644 --- a/packages/kbn-ci-stats-reporter/package.json +++ b/packages/kbn-ci-stats-reporter/package.json @@ -3,8 +3,5 @@ "private": true, "version": "1.0.0", "main": "./target_node/index.js", - "license": "SSPL-1.0 OR Elastic License 2.0", - "kibana": { - "devOnly": true - } + "license": "SSPL-1.0 OR Elastic License 2.0" } diff --git a/packages/kbn-cli-dev-mode/kibana.jsonc b/packages/kbn-cli-dev-mode/kibana.jsonc new file mode 100644 index 00000000000000..18c9cb7ba46a02 --- /dev/null +++ b/packages/kbn-cli-dev-mode/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/cli-dev-mode", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-cli-dev-mode/package.json b/packages/kbn-cli-dev-mode/package.json index 80076a98510879..6113b1deef073e 100644 --- a/packages/kbn-cli-dev-mode/package.json +++ b/packages/kbn-cli-dev-mode/package.json @@ -3,8 +3,5 @@ "main": "./target_node/index.js", "version": "1.0.0", "license": "SSPL-1.0 OR Elastic License 2.0", - "private": true, - "kibana": { - "devOnly": true - } + "private": true } \ No newline at end of file diff --git a/packages/kbn-coloring/kibana.jsonc b/packages/kbn-coloring/kibana.jsonc new file mode 100644 index 00000000000000..0b1ff8a4492864 --- /dev/null +++ b/packages/kbn-coloring/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/coloring", + "owner": "@elastic/kibana-vis-editors", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-config-mocks/kibana.jsonc b/packages/kbn-config-mocks/kibana.jsonc new file mode 100644 index 00000000000000..de1d13289e8ff5 --- /dev/null +++ b/packages/kbn-config-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/config-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-config-schema/kibana.jsonc b/packages/kbn-config-schema/kibana.jsonc new file mode 100644 index 00000000000000..c8895557086756 --- /dev/null +++ b/packages/kbn-config-schema/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/config-schema", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-config/kibana.jsonc b/packages/kbn-config/kibana.jsonc new file mode 100644 index 00000000000000..e3bac638520bdb --- /dev/null +++ b/packages/kbn-config/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/config", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-crypto-browser/kibana.jsonc b/packages/kbn-crypto-browser/kibana.jsonc new file mode 100644 index 00000000000000..9faf12c5f05b0b --- /dev/null +++ b/packages/kbn-crypto-browser/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/crypto-browser", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-crypto/kibana.jsonc b/packages/kbn-crypto/kibana.jsonc new file mode 100644 index 00000000000000..21f9cbbc81c74a --- /dev/null +++ b/packages/kbn-crypto/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/crypto", + "owner": "@elastic/kibana-security", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-datemath/kibana.jsonc b/packages/kbn-datemath/kibana.jsonc new file mode 100644 index 00000000000000..85522ceb11b9ef --- /dev/null +++ b/packages/kbn-datemath/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/datemath", + "owner": "@elastic/kibana-app-services", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-dev-cli-errors/kibana.jsonc b/packages/kbn-dev-cli-errors/kibana.jsonc new file mode 100644 index 00000000000000..66a63cdce30749 --- /dev/null +++ b/packages/kbn-dev-cli-errors/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/dev-cli-errors", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-dev-cli-errors/package.json b/packages/kbn-dev-cli-errors/package.json index 62e1465933a523..e4757b7ad9b383 100644 --- a/packages/kbn-dev-cli-errors/package.json +++ b/packages/kbn-dev-cli-errors/package.json @@ -3,8 +3,5 @@ "private": true, "version": "1.0.0", "main": "./target_node/index.js", - "license": "SSPL-1.0 OR Elastic License 2.0", - "kibana": { - "devOnly": true - } + "license": "SSPL-1.0 OR Elastic License 2.0" } diff --git a/packages/kbn-dev-cli-runner/kibana.jsonc b/packages/kbn-dev-cli-runner/kibana.jsonc new file mode 100644 index 00000000000000..43e1b39ab17f2b --- /dev/null +++ b/packages/kbn-dev-cli-runner/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/dev-cli-runner", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-dev-cli-runner/package.json b/packages/kbn-dev-cli-runner/package.json index 779d6f48a4fb7a..12670190159afe 100644 --- a/packages/kbn-dev-cli-runner/package.json +++ b/packages/kbn-dev-cli-runner/package.json @@ -3,8 +3,5 @@ "private": true, "version": "1.0.0", "main": "./target_node/index.js", - "license": "SSPL-1.0 OR Elastic License 2.0", - "kibana": { - "devOnly": true - } + "license": "SSPL-1.0 OR Elastic License 2.0" } diff --git a/packages/kbn-dev-proc-runner/kibana.jsonc b/packages/kbn-dev-proc-runner/kibana.jsonc new file mode 100644 index 00000000000000..e028b7e7d795d6 --- /dev/null +++ b/packages/kbn-dev-proc-runner/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/dev-proc-runner", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-dev-proc-runner/package.json b/packages/kbn-dev-proc-runner/package.json index 2de282a948edac..38907397d2c528 100644 --- a/packages/kbn-dev-proc-runner/package.json +++ b/packages/kbn-dev-proc-runner/package.json @@ -3,8 +3,5 @@ "private": true, "version": "1.0.0", "main": "./target_node/index.js", - "license": "SSPL-1.0 OR Elastic License 2.0", - "kibana": { - "devOnly": true - } + "license": "SSPL-1.0 OR Elastic License 2.0" } diff --git a/packages/kbn-dev-utils/kibana.jsonc b/packages/kbn-dev-utils/kibana.jsonc new file mode 100644 index 00000000000000..7a9e4e644dcf02 --- /dev/null +++ b/packages/kbn-dev-utils/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/dev-utils", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-dev-utils/package.json b/packages/kbn-dev-utils/package.json index ab4f489e7d345b..1316319286a963 100644 --- a/packages/kbn-dev-utils/package.json +++ b/packages/kbn-dev-utils/package.json @@ -3,8 +3,5 @@ "version": "1.0.0", "private": true, "license": "SSPL-1.0 OR Elastic License 2.0", - "main": "./target_node/index.js", - "kibana": { - "devOnly": true - } + "main": "./target_node/index.js" } \ No newline at end of file diff --git a/packages/kbn-doc-links/kibana.jsonc b/packages/kbn-doc-links/kibana.jsonc new file mode 100644 index 00000000000000..a3af199f6c32e7 --- /dev/null +++ b/packages/kbn-doc-links/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/doc-links", + "owner": "@elastic/kibana-docs", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-doc-links/src/get_doc_links.ts b/packages/kbn-doc-links/src/get_doc_links.ts index ecef81171b241c..7b7c57ff4f7f25 100644 --- a/packages/kbn-doc-links/src/get_doc_links.ts +++ b/packages/kbn-doc-links/src/get_doc_links.ts @@ -126,6 +126,7 @@ export const getDocLinks = ({ kibanaBranch }: GetDocLinkOptions): DocLinks => { crawlerManaging: `${ENTERPRISE_SEARCH_DOCS}crawler-managing.html`, crawlerOverview: `${ENTERPRISE_SEARCH_DOCS}crawler.html`, languageAnalyzers: `${ELASTICSEARCH_DOCS}analysis-lang-analyzer.html`, + languageClients: `${ENTERPRISE_SEARCH_DOCS}programming-language-clients.html`, licenseManagement: `${ENTERPRISE_SEARCH_DOCS}license-management.html`, mailService: `${ENTERPRISE_SEARCH_DOCS}mailer-configuration.html`, start: `${ENTERPRISE_SEARCH_DOCS}start.html`, diff --git a/packages/kbn-doc-links/src/types.ts b/packages/kbn-doc-links/src/types.ts index 99396183fc64f6..fb934f4aa4f2ab 100644 --- a/packages/kbn-doc-links/src/types.ts +++ b/packages/kbn-doc-links/src/types.ts @@ -112,6 +112,7 @@ export interface DocLinks { readonly crawlerManaging: string; readonly crawlerOverview: string; readonly languageAnalyzers: string; + readonly languageClients: string; readonly licenseManagement: string; readonly mailService: string; readonly start: string; diff --git a/packages/kbn-docs-utils/kibana.jsonc b/packages/kbn-docs-utils/kibana.jsonc new file mode 100644 index 00000000000000..5e0ea2367d5317 --- /dev/null +++ b/packages/kbn-docs-utils/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/docs-utils", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-docs-utils/package.json b/packages/kbn-docs-utils/package.json index 84fc3ccb0cded7..d75a79ed44b225 100644 --- a/packages/kbn-docs-utils/package.json +++ b/packages/kbn-docs-utils/package.json @@ -3,8 +3,5 @@ "version": "1.0.0", "license": "SSPL-1.0 OR Elastic License 2.0", "private": "true", - "main": "target_node/index.js", - "kibana": { - "devOnly": true - } + "main": "target_node/index.js" } \ No newline at end of file diff --git a/packages/kbn-ebt-tools/kibana.jsonc b/packages/kbn-ebt-tools/kibana.jsonc new file mode 100644 index 00000000000000..f9fde6d48f0465 --- /dev/null +++ b/packages/kbn-ebt-tools/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/ebt-tools", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-es-archiver/kibana.jsonc b/packages/kbn-es-archiver/kibana.jsonc new file mode 100644 index 00000000000000..cc2b4530ea552d --- /dev/null +++ b/packages/kbn-es-archiver/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/es-archiver", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-es-archiver/package.json b/packages/kbn-es-archiver/package.json index bff3990a0c1bcd..ddd55875664e39 100644 --- a/packages/kbn-es-archiver/package.json +++ b/packages/kbn-es-archiver/package.json @@ -3,8 +3,5 @@ "version": "1.0.0", "license": "SSPL-1.0 OR Elastic License 2.0", "private": "true", - "main": "target_node/index.js", - "kibana": { - "devOnly": true - } + "main": "target_node/index.js" } diff --git a/packages/kbn-es-errors/kibana.jsonc b/packages/kbn-es-errors/kibana.jsonc new file mode 100644 index 00000000000000..3a121caaf95cc4 --- /dev/null +++ b/packages/kbn-es-errors/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/es-errors", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-es-query/kibana.jsonc b/packages/kbn-es-query/kibana.jsonc new file mode 100644 index 00000000000000..2bd959eec53eb9 --- /dev/null +++ b/packages/kbn-es-query/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/es-query", + "owner": "@elastic/kibana-app-services", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-es/kibana.jsonc b/packages/kbn-es/kibana.jsonc new file mode 100644 index 00000000000000..6407107c3639c0 --- /dev/null +++ b/packages/kbn-es/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/es", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-es/package.json b/packages/kbn-es/package.json index ee8d8e89030e16..38c138d6883622 100644 --- a/packages/kbn-es/package.json +++ b/packages/kbn-es/package.json @@ -3,8 +3,5 @@ "main": "./target_node/index.js", "version": "1.0.0", "license": "SSPL-1.0 OR Elastic License 2.0", - "private": true, - "kibana": { - "devOnly": true - } + "private": true } \ No newline at end of file diff --git a/packages/kbn-eslint-config/kibana.jsonc b/packages/kbn-eslint-config/kibana.jsonc new file mode 100644 index 00000000000000..3afe0461c4861d --- /dev/null +++ b/packages/kbn-eslint-config/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/eslint-config", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-eslint-config/package.json b/packages/kbn-eslint-config/package.json index eb9f7a4b08246b..76082ec00ee44f 100644 --- a/packages/kbn-eslint-config/package.json +++ b/packages/kbn-eslint-config/package.json @@ -7,9 +7,6 @@ "type": "git", "url": "git+https://github.com/elastic/kibana.git" }, - "kibana": { - "devOnly": true - }, "keywords": [], "author": "Spencer Alger ", "license": "Apache-2.0", diff --git a/packages/kbn-eslint-plugin-disable/kibana.jsonc b/packages/kbn-eslint-plugin-disable/kibana.jsonc new file mode 100644 index 00000000000000..43a4d8f8f90bb2 --- /dev/null +++ b/packages/kbn-eslint-plugin-disable/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/eslint-plugin-disable", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-eslint-plugin-eslint/kibana.jsonc b/packages/kbn-eslint-plugin-eslint/kibana.jsonc new file mode 100644 index 00000000000000..fc9c384c415627 --- /dev/null +++ b/packages/kbn-eslint-plugin-eslint/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/eslint-plugin-eslint", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-eslint-plugin-eslint/package.json b/packages/kbn-eslint-plugin-eslint/package.json index ffce2cbefe743a..c1f126223b27c6 100644 --- a/packages/kbn-eslint-plugin-eslint/package.json +++ b/packages/kbn-eslint-plugin-eslint/package.json @@ -2,8 +2,5 @@ "name": "@kbn/eslint-plugin-eslint", "version": "1.0.0", "private": true, - "license": "SSPL-1.0 OR Elastic License 2.0", - "kibana": { - "devOnly": true - } + "license": "SSPL-1.0 OR Elastic License 2.0" } diff --git a/packages/kbn-eslint-plugin-imports/kibana.jsonc b/packages/kbn-eslint-plugin-imports/kibana.jsonc new file mode 100644 index 00000000000000..658733d10535b1 --- /dev/null +++ b/packages/kbn-eslint-plugin-imports/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/eslint-plugin-imports", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-expect/kibana.jsonc b/packages/kbn-expect/kibana.jsonc new file mode 100644 index 00000000000000..53f789961dd333 --- /dev/null +++ b/packages/kbn-expect/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/expect", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-expect/package.json b/packages/kbn-expect/package.json index 2040683c539e2d..fb732269fef975 100644 --- a/packages/kbn-expect/package.json +++ b/packages/kbn-expect/package.json @@ -4,8 +4,5 @@ "typings": "./expect.d.ts", "version": "1.0.0", "license": "MIT", - "private": true, - "kibana": { - "devOnly": true - } + "private": true } diff --git a/packages/kbn-field-types/kibana.jsonc b/packages/kbn-field-types/kibana.jsonc new file mode 100644 index 00000000000000..5bcf1740370084 --- /dev/null +++ b/packages/kbn-field-types/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/field-types", + "owner": "@elastic/kibana-app-services", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-find-used-node-modules/kibana.jsonc b/packages/kbn-find-used-node-modules/kibana.jsonc new file mode 100644 index 00000000000000..d5c72f59277376 --- /dev/null +++ b/packages/kbn-find-used-node-modules/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/find-used-node-modules", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-find-used-node-modules/package.json b/packages/kbn-find-used-node-modules/package.json index c5da8d1f898c12..138a77f3ed2861 100644 --- a/packages/kbn-find-used-node-modules/package.json +++ b/packages/kbn-find-used-node-modules/package.json @@ -3,8 +3,5 @@ "private": true, "version": "1.0.0", "main": "./target_node/index.js", - "license": "SSPL-1.0 OR Elastic License 2.0", - "kibana": { - "devOnly": true - } + "license": "SSPL-1.0 OR Elastic License 2.0" } diff --git a/packages/kbn-flot-charts/kibana.jsonc b/packages/kbn-flot-charts/kibana.jsonc new file mode 100644 index 00000000000000..ad96bcf118b1b0 --- /dev/null +++ b/packages/kbn-flot-charts/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/flot-charts", + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-generate/kibana.jsonc b/packages/kbn-generate/kibana.jsonc new file mode 100644 index 00000000000000..d7d38e4822cb77 --- /dev/null +++ b/packages/kbn-generate/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/generate", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-generate/package.json b/packages/kbn-generate/package.json index aacf8c6aab817a..8413023c99a2d5 100644 --- a/packages/kbn-generate/package.json +++ b/packages/kbn-generate/package.json @@ -3,8 +3,5 @@ "version": "1.0.0", "private": true, "license": "SSPL-1.0 OR Elastic License 2.0", - "main": "./target_node/index.js", - "kibana": { - "devOnly": true - } + "main": "./target_node/index.js" } \ No newline at end of file diff --git a/packages/kbn-generate/src/cli.ts b/packages/kbn-generate/src/cli.ts index 81e7a8cb85b55b..d3d1366682feac 100644 --- a/packages/kbn-generate/src/cli.ts +++ b/packages/kbn-generate/src/cli.ts @@ -12,6 +12,7 @@ import { Render } from './lib/render'; import { ContextExtensions } from './generate_command'; import { PackageCommand } from './commands/package_command'; +import { CodeownersCommand } from './commands/codeowners_command'; import { PackagesBuildManifestCommand } from './commands/packages_build_manifest_command'; /** @@ -27,6 +28,6 @@ export function runGenerateCli() { }; }, }, - [PackageCommand, PackagesBuildManifestCommand] + [PackageCommand, PackagesBuildManifestCommand, CodeownersCommand] ).execute(); } diff --git a/packages/kbn-generate/src/commands/codeowners_command.ts b/packages/kbn-generate/src/commands/codeowners_command.ts new file mode 100644 index 00000000000000..7478f342c0d9a6 --- /dev/null +++ b/packages/kbn-generate/src/commands/codeowners_command.ts @@ -0,0 +1,56 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import Fsp from 'fs/promises'; +import Path from 'path'; + +import { REPO_ROOT } from '@kbn/utils'; +import { discoverBazelPackages } from '@kbn/bazel-packages'; + +import type { GenerateCommand } from '../generate_command'; + +const REL = '.github/CODEOWNERS'; + +const GENERATED_START = ` + +#### +## Everything below this comment is automatically generated based on kibana.jsonc +## "owner" fields. This file is automatically updated by CI or can be updated locally +## by running \`node scripts/generate codeowners\`. +#### + +`; + +export const CodeownersCommand: GenerateCommand = { + name: 'codeowners', + description: 'Update the codeowners file based on the package manifest files', + usage: 'node scripts/generate codeowners', + async run({ log }) { + const coPath = Path.resolve(REPO_ROOT, REL); + const codeowners = await Fsp.readFile(coPath, 'utf8'); + const pkgs = await discoverBazelPackages(REPO_ROOT); + + let genStart = codeowners.indexOf(GENERATED_START); + if (genStart === -1) { + genStart = codeowners.length; + log.warning(`${REL} doesn't include the expected start-marker for injecting generated text`); + } + + const newCodeowners = `${codeowners.slice(0, genStart)}${GENERATED_START}${pkgs + .map((pkg) => `${pkg.normalizedRepoRelativeDir} ${pkg.manifest.owner}`) + .join('\n')}\n`; + + if (codeowners === newCodeowners) { + log.success(`${REL} is already up-to-date`); + return; + } + + await Fsp.writeFile(coPath, newCodeowners); + log.info(`${REL} updated`); + }, +}; diff --git a/packages/kbn-generate/src/commands/package_command.ts b/packages/kbn-generate/src/commands/package_command.ts index 32d5ff008c79f4..ecfd2eb5f3d21c 100644 --- a/packages/kbn-generate/src/commands/package_command.ts +++ b/packages/kbn-generate/src/commands/package_command.ts @@ -19,16 +19,21 @@ import { discoverBazelPackages, BAZEL_PACKAGE_DIRS } from '@kbn/bazel-packages'; import { createFailError, createFlagError, isFailError } from '@kbn/dev-cli-errors'; import { sortPackageJson } from '@kbn/sort-package-json'; +import { validateElasticTeam } from '../lib/validate_elastic_team'; import { TEMPLATE_DIR, ROOT_PKG_DIR, PKG_TEMPLATE_DIR } from '../paths'; import type { GenerateCommand } from '../generate_command'; +import { ask } from '../lib/ask'; + +const validPkgId = (id: unknown): id is string => + typeof id === 'string' && id.startsWith('@kbn/') && !id.includes(' '); export const PackageCommand: GenerateCommand = { name: 'package', description: 'Generate a basic package', - usage: 'node scripts/generate package [name]', + usage: 'node scripts/generate package [pkgId]', flags: { boolean: ['web', 'force', 'dev'], - string: ['dir'], + string: ['dir', 'owner'], help: ` --dev Generate a package which is intended for dev-only use and can access things like devDependencies --web Build webpack-compatible version of sources for this package. If your package is intended to be @@ -39,24 +44,37 @@ export const PackageCommand: GenerateCommand = { ${BAZEL_PACKAGE_DIRS.map((dir) => ` ./${dir}/*\n`).join('')} defaults to [./packages/{kebab-case-version-of-name}] --force If the --dir already exists, delete it before generation + --owner Github username of the owner for this package, if this is not specified then you will be asked for + this value interactively. `, }, async run({ log, flags, render }) { - const [name] = flags._; - if (!name) { - throw createFlagError(`missing package name`); - } - if (!name.startsWith('@kbn/')) { - throw createFlagError(`package name must start with @kbn/`); + const pkgId = + flags._[0] || + (await ask({ + question: `What should the package id be? (Must start with @kbn/ and have no spaces)`, + async validate(input) { + if (validPkgId(input)) { + return input; + } + + return { + err: `"${input}" must start with @kbn/ and have no spaces`, + }; + }, + })); + + if (!validPkgId(pkgId)) { + throw createFlagError(`package id must start with @kbn/ and have no spaces`); } - const typePkgName = `@types/${name.slice(1).replace('/', '__')}`; + const typePkgName = `@types/${pkgId.slice(1).replace('/', '__')}`; const web = !!flags.web; const dev = !!flags.dev; const packageDir = flags.dir ? Path.resolve(`${flags.dir}`) - : Path.resolve(ROOT_PKG_DIR, name.slice(1).replace('/', '-')); + : Path.resolve(ROOT_PKG_DIR, pkgId.slice(1).replace('/', '-')); const relContainingDir = Path.relative(REPO_ROOT, Path.dirname(packageDir)); if (!micromatch.isMatch(relContainingDir, BAZEL_PACKAGE_DIRS)) { throw createFlagError( @@ -82,13 +100,29 @@ ${BAZEL_PACKAGE_DIRS.map((dir) => ` ./${dir}/*\n`).join } } + const owner = + flags.owner || + (await ask({ + question: 'Which Elastic team should own this package? (Must start with "@elastic/")', + async validate(input) { + try { + return await validateElasticTeam(input); + } catch (error) { + log.error(`failed to validate team: ${error.message}`); + return input; + } + }, + })); + if (typeof owner !== 'string' || !owner.startsWith('@')) { + throw createFlagError(`expected --owner to be a string starting with an @ symbol`); + } + const templateFiles = await globby('**/*', { cwd: PKG_TEMPLATE_DIR, absolute: false, dot: true, onlyFiles: true, }); - if (!templateFiles.length) { throw new Error('unable to find package template files'); } @@ -119,9 +153,10 @@ ${BAZEL_PACKAGE_DIRS.map((dir) => ` ./${dir}/*\n`).join await render.toFile(src, dest, { pkg: { - name, + id: pkgId, web, dev, + owner, directoryName: Path.basename(normalizedRepoRelativeDir), normalizedRepoRelativeDir, }, @@ -146,8 +181,8 @@ ${BAZEL_PACKAGE_DIRS.map((dir) => ` ./${dir}/*\n`).join ? [packageJson.devDependencies, packageJson.dependencies] : [packageJson.dependencies, packageJson.devDependencies]; - addDeps[name] = `link:bazel-bin/${normalizedRepoRelativeDir}`; - delete removeDeps[name]; + addDeps[pkgId] = `link:bazel-bin/${normalizedRepoRelativeDir}`; + delete removeDeps[pkgId]; // for @types packages always remove from deps and add to devDeps packageJson.devDependencies[ @@ -167,6 +202,6 @@ ${BAZEL_PACKAGE_DIRS.map((dir) => ` ./${dir}/*\n`).join ); log.info('Updated packages/BUILD.bazel'); - log.success(`Generated ${name}! Please bootstrap to make sure it works.`); + log.success(`Generated ${pkgId}! Please bootstrap to make sure it works.`); }, }; diff --git a/packages/kbn-generate/src/commands/packages_build_manifest_command.ts b/packages/kbn-generate/src/commands/packages_build_manifest_command.ts index 9b05c1aed332de..4e277534798533 100644 --- a/packages/kbn-generate/src/commands/packages_build_manifest_command.ts +++ b/packages/kbn-generate/src/commands/packages_build_manifest_command.ts @@ -14,7 +14,6 @@ import { discoverBazelPackages } from '@kbn/bazel-packages'; import { TEMPLATE_DIR } from '../paths'; import { GenerateCommand } from '../generate_command'; -import { validateFile } from '../lib/validate_file'; const USAGE = `node scripts/generate packages_build_manifest`; @@ -22,15 +21,7 @@ export const PackagesBuildManifestCommand: GenerateCommand = { name: 'packages_build_manifest', usage: USAGE, description: 'Generate the packages/BUILD.bazel file', - flags: { - boolean: ['validate'], - help: ` - --validate Rather than writing the generated output to disk, validate that the content on disk is in sync with the - `, - }, - async run({ log, render, flags }) { - const validate = !!flags.validate; - + async run({ log, render }) { const packages = await discoverBazelPackages(REPO_ROOT); const dest = Path.resolve(REPO_ROOT, 'packages/BUILD.bazel'); const relDest = Path.relative(process.cwd(), dest); @@ -38,17 +29,22 @@ export const PackagesBuildManifestCommand: GenerateCommand = { const content = await render.toString( Path.join(TEMPLATE_DIR, 'packages_BUILD.bazel.ejs'), dest, - { - packages, - } + { packages } ); - if (validate) { - await validateFile(log, USAGE, dest, content); + let existing; + try { + existing = await Fsp.readFile(dest, 'utf8'); + } catch { + // noop + } + + if (existing === content) { + log.success(relDest, 'is already updated'); return; } await Fsp.writeFile(dest, content); - log.success('Wrote', relDest); + log.info(relDest, 'updated'); }, }; diff --git a/packages/kbn-generate/src/lib/ansi.ts b/packages/kbn-generate/src/lib/ansi.ts new file mode 100644 index 00000000000000..4fe360b510b3c5 --- /dev/null +++ b/packages/kbn-generate/src/lib/ansi.ts @@ -0,0 +1,10 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +// https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797 +export const CLEAR_LINE_AND_MOVE_LEFT = `\x1B[2K\x1B[0G`; diff --git a/packages/kbn-generate/src/lib/ask.ts b/packages/kbn-generate/src/lib/ask.ts new file mode 100644 index 00000000000000..e5e33e8df058c9 --- /dev/null +++ b/packages/kbn-generate/src/lib/ask.ts @@ -0,0 +1,83 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import Chalk from 'chalk'; +import Readline from 'readline'; +import * as Rx from 'rxjs'; +import Util from 'util'; + +import * as Ansi from './ansi'; + +export type ValidationResult = string | { err: string }; + +interface Options { + question: string; + validate(input: string): Promise; +} + +export async function ask(options: Options) { + if (!process.stderr.isTTY) { + return undefined; + } + + const int = Readline.createInterface({ + input: process.stdin, + output: process.stderr, + }); + + const q = Util.promisify(int.question) as unknown as (q: string) => Promise; + + try { + return await Rx.firstValueFrom( + Rx.race( + Rx.fromEvent(int, 'error').pipe( + Rx.map((err) => { + throw err; + }) + ), + Rx.defer(() => q.call(int, `${Chalk.blueBright('?')} ${options.question} > `)).pipe( + Rx.mergeMap(async (answer) => { + process.stderr.write('validating...'); + try { + return await options.validate(answer); + } finally { + process.stderr.write(Ansi.CLEAR_LINE_AND_MOVE_LEFT); + } + }), + Rx.map((valid) => { + if (typeof valid === 'string') { + return valid; + } + + const label = `Error:`; + const indent = ' '.repeat(label.length + 1); + const indented = valid.err + .split('\n') + .map((l, i) => (i === 0 ? l : `${indent}${l}`)) + .join('\n'); + + process.stderr.write(`${Chalk.bgRed.white(label)} ${indented}\n`); + + throw new Error('retry'); + }), + Rx.retry({ + delay: (err) => { + if (typeof err === 'object' && err && err.message === 'retry') { + return Rx.of(1); + } else { + throw err; + } + }, + }) + ) + ) + ); + } finally { + int.close(); + } +} diff --git a/packages/kbn-generate/src/lib/validate_elastic_team.ts b/packages/kbn-generate/src/lib/validate_elastic_team.ts new file mode 100644 index 00000000000000..89138d59641c76 --- /dev/null +++ b/packages/kbn-generate/src/lib/validate_elastic_team.ts @@ -0,0 +1,41 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import Axios from 'axios'; +import { ValidationResult } from './ask'; + +interface Body { + match?: string; + suggestions: string[]; +} + +export async function validateElasticTeam(owner: string): Promise { + const slug = owner.startsWith('@') ? owner.slice(1) : owner; + + const res = await Axios.get('https://ci-stats.kibana.dev/v1/_validate_kibana_team', { + params: { + slug, + }, + timeout: 5000, + }); + + if (res.data.match) { + return `@${res.data.match}`; + } + + const err = `"${owner}" doesn't match any @elastic team, to override with another valid Github user pass the value with the --owner flag`; + + if (!res.data.suggestions?.length) { + return { err }; + } + + const list = res.data.suggestions.map((l) => ` @${l}`); + return { + err: `${err}\n Did you mean one of these?\n${list.join('\n')}`, + }; +} diff --git a/packages/kbn-generate/src/lib/validate_file.ts b/packages/kbn-generate/src/lib/validate_file.ts deleted file mode 100644 index 342a25e3d193d7..00000000000000 --- a/packages/kbn-generate/src/lib/validate_file.ts +++ /dev/null @@ -1,36 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import Fsp from 'fs/promises'; -import Path from 'path'; - -import { diffStrings } from '@kbn/dev-utils'; -import { createFailError } from '@kbn/dev-cli-errors'; -import { ToolingLog } from '@kbn/tooling-log'; - -export async function validateFile(log: ToolingLog, usage: string, path: string, expected: string) { - const relPath = Path.relative(process.cwd(), path); - - let current; - try { - current = await Fsp.readFile(path, 'utf8'); - } catch (error) { - if (error && error.code === 'ENOENT') { - throw createFailError(`${relPath} is missing, please run "${usage}" and commit the result`); - } - - throw error; - } - - if (current !== expected) { - log.error(`${relPath} is outdated:\n${diffStrings(expected, current)}`); - throw createFailError(`${relPath} is outdated, please run "${usage}" and commit the result`); - } - - log.success(`${relPath} is valid`); -} diff --git a/packages/kbn-generate/templates/package/BUILD.bazel.ejs b/packages/kbn-generate/templates/package/BUILD.bazel.ejs index c66f67e93b15c7..cb1d250f468e98 100644 --- a/packages/kbn-generate/templates/package/BUILD.bazel.ejs +++ b/packages/kbn-generate/templates/package/BUILD.bazel.ejs @@ -3,7 +3,7 @@ load("@build_bazel_rules_nodejs//:index.bzl", "js_library") load("//src/dev/bazel:index.bzl", "jsts_transpiler", "pkg_npm", "pkg_npm_types", "ts_project") PKG_DIRNAME = <%- json(pkg.directoryName) %> -PKG_REQUIRE_NAME = <%- json(pkg.name) %> +PKG_REQUIRE_NAME = <%- json(pkg.id) %> SOURCE_FILES = glob( [ diff --git a/packages/kbn-generate/templates/package/README.md.ejs b/packages/kbn-generate/templates/package/README.md.ejs index 769f536648a6d9..826a90cb80987e 100644 --- a/packages/kbn-generate/templates/package/README.md.ejs +++ b/packages/kbn-generate/templates/package/README.md.ejs @@ -1,3 +1,3 @@ -# <%- pkg.name %> +# <%- pkg.id %> Empty package generated by @kbn/generate diff --git a/packages/kbn-generate/templates/package/kibana.jsonc.ejs b/packages/kbn-generate/templates/package/kibana.jsonc.ejs new file mode 100644 index 00000000000000..f39655160f82f7 --- /dev/null +++ b/packages/kbn-generate/templates/package/kibana.jsonc.ejs @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": <%- json(pkg.id) %>, + "owner": <%- json(pkg.owner) %>,<% if (pkg.dev) { %> + "devOnly": true,<% } %> + "runtimeDeps": [], + "typeDeps": [], +} diff --git a/packages/kbn-generate/templates/package/package.json.ejs b/packages/kbn-generate/templates/package/package.json.ejs index 93b2813daffa12..44f53c0a1324cf 100644 --- a/packages/kbn-generate/templates/package/package.json.ejs +++ b/packages/kbn-generate/templates/package/package.json.ejs @@ -1,5 +1,5 @@ { - "name": <%- json(pkg.name) %>, + "name": <%- json(pkg.id) %>, "version": "1.0.0", "private": true, "license": "SSPL-1.0 OR Elastic License 2.0", @@ -7,9 +7,4 @@ <%_ if (pkg.web) { %>, "browser": "./target_web/index.js" <%_ } %> - <% if (pkg.dev) { %>, - "kibana": { - "devOnly": true - } - <% } %> } diff --git a/packages/kbn-get-repo-files/kibana.jsonc b/packages/kbn-get-repo-files/kibana.jsonc new file mode 100644 index 00000000000000..44ee4e026ba7ed --- /dev/null +++ b/packages/kbn-get-repo-files/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/get-repo-files", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-get-repo-files/package.json b/packages/kbn-get-repo-files/package.json index 8cd19049fd1979..21aa7c24d2b828 100644 --- a/packages/kbn-get-repo-files/package.json +++ b/packages/kbn-get-repo-files/package.json @@ -3,8 +3,5 @@ "private": true, "version": "1.0.0", "main": "./target_node/index.js", - "license": "SSPL-1.0 OR Elastic License 2.0", - "kibana": { - "devOnly": true - } + "license": "SSPL-1.0 OR Elastic License 2.0" } diff --git a/packages/kbn-handlebars/kibana.jsonc b/packages/kbn-handlebars/kibana.jsonc new file mode 100644 index 00000000000000..64249345bce8e2 --- /dev/null +++ b/packages/kbn-handlebars/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/handlebars", + "owner": "@elastic/kibana-security", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-hapi-mocks/kibana.jsonc b/packages/kbn-hapi-mocks/kibana.jsonc new file mode 100644 index 00000000000000..9a2632c95d8144 --- /dev/null +++ b/packages/kbn-hapi-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/hapi-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-i18n-react/kibana.jsonc b/packages/kbn-i18n-react/kibana.jsonc new file mode 100644 index 00000000000000..296e7295e52b67 --- /dev/null +++ b/packages/kbn-i18n-react/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/i18n-react", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-i18n/kibana.jsonc b/packages/kbn-i18n/kibana.jsonc new file mode 100644 index 00000000000000..cd5613bc493c0a --- /dev/null +++ b/packages/kbn-i18n/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/i18n", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-import-resolver/kibana.jsonc b/packages/kbn-import-resolver/kibana.jsonc new file mode 100644 index 00000000000000..9e059869662101 --- /dev/null +++ b/packages/kbn-import-resolver/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/import-resolver", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-import-resolver/package.json b/packages/kbn-import-resolver/package.json index d8a6e72792399a..a809d48bc24107 100644 --- a/packages/kbn-import-resolver/package.json +++ b/packages/kbn-import-resolver/package.json @@ -3,8 +3,5 @@ "private": true, "version": "1.0.0", "main": "./target_node/index.js", - "license": "SSPL-1.0 OR Elastic License 2.0", - "kibana": { - "devOnly": true - } + "license": "SSPL-1.0 OR Elastic License 2.0" } diff --git a/packages/kbn-import-resolver/src/import_resolver.ts b/packages/kbn-import-resolver/src/import_resolver.ts index 05b69f299a798b..74e2ed52ca453d 100644 --- a/packages/kbn-import-resolver/src/import_resolver.ts +++ b/packages/kbn-import-resolver/src/import_resolver.ts @@ -7,12 +7,12 @@ */ import Path from 'path'; -import Fs from 'fs'; import Resolve from 'resolve'; +import { readPackageManifest } from '@kbn/bazel-packages'; import { REPO_ROOT } from '@kbn/utils'; import normalizePath from 'normalize-path'; -import { discoverBazelPackageLocations } from '@kbn/bazel-packages'; +import { discoverPackageManifestPaths } from '@kbn/bazel-packages'; import { readPackageMap, PackageMap } from '@kbn/synthetic-package-map'; import { safeStat, readFileSync } from './helpers/fs'; @@ -25,18 +25,10 @@ const NODE_MODULE_SEG = Path.sep + 'node_modules' + Path.sep; export class ImportResolver { static create(repoRoot: string) { const pkgMap = new Map(); - for (const dir of discoverBazelPackageLocations(REPO_ROOT)) { - const relativeBazelPackageDir = Path.relative(REPO_ROOT, dir); - const repoRootBazelPackageDir = Path.resolve(repoRoot, relativeBazelPackageDir); - - if (!Fs.existsSync(Path.resolve(repoRootBazelPackageDir, 'package.json'))) { - continue; - } - - const pkg = JSON.parse( - Fs.readFileSync(Path.resolve(repoRootBazelPackageDir, 'package.json'), 'utf8') - ); - pkgMap.set(pkg.name, normalizePath(relativeBazelPackageDir)); + for (const manifestPath of discoverPackageManifestPaths(REPO_ROOT)) { + const relativeBazelPackageDir = Path.relative(REPO_ROOT, Path.dirname(manifestPath)); + const pkg = readPackageManifest(manifestPath); + pkgMap.set(pkg.id, normalizePath(relativeBazelPackageDir)); } return new ImportResolver(repoRoot, pkgMap, readPackageMap()); diff --git a/packages/kbn-interpreter/kibana.jsonc b/packages/kbn-interpreter/kibana.jsonc new file mode 100644 index 00000000000000..5439509b2c0c7b --- /dev/null +++ b/packages/kbn-interpreter/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/interpreter", + "owner": "@elastic/kibana-app-services", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-io-ts-utils/kibana.jsonc b/packages/kbn-io-ts-utils/kibana.jsonc new file mode 100644 index 00000000000000..f903e878366b23 --- /dev/null +++ b/packages/kbn-io-ts-utils/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/io-ts-utils", + "owner": "@elastic/apm-ui", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-jest-serializers/kibana.jsonc b/packages/kbn-jest-serializers/kibana.jsonc new file mode 100644 index 00000000000000..2742ade92e31ac --- /dev/null +++ b/packages/kbn-jest-serializers/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/jest-serializers", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-jest-serializers/package.json b/packages/kbn-jest-serializers/package.json index c049ef67251579..1f6642f0557fd7 100644 --- a/packages/kbn-jest-serializers/package.json +++ b/packages/kbn-jest-serializers/package.json @@ -3,8 +3,5 @@ "private": true, "version": "1.0.0", "main": "./target_node/index.js", - "license": "SSPL-1.0 OR Elastic License 2.0", - "kibana": { - "devOnly": true - } + "license": "SSPL-1.0 OR Elastic License 2.0" } diff --git a/packages/kbn-jsonc/README.mdx b/packages/kbn-jsonc/README.mdx deleted file mode 100644 index 79ab8fc52bd92b..00000000000000 --- a/packages/kbn-jsonc/README.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -id: kibDevDocsOpsJsonc -slug: /kibana-dev-docs/ops/jsonc -title: "@kbn/jsonc" -description: A package for parsing jsonc -date: 2022-05-24 -tags: ['kibana', 'dev', 'contributor', 'operations', 'json', 'jsonc'] ---- - -This package exposes a simple `parse(jsonc: string)` function for parsing JSON-C content. JSON-C is a variant of JSON which supports both block and line comments, which are incredibly useful for configuration files that are committed to the repository and would benefit from the context of comments. - -Additionally supported in JSON-C... TRAILING COMMAS! - -VSCode and TypeScript use jsonc for their config files, so we're already using it in a lot of places, but we're going to start using it in more places too. This package is implemented in vanilla JS with a vendored copy of [`strip-json-comments`](https://github.com/sindresorhus/strip-json-comments) so that we can use this code from kbn_pm without node modules installed. - -## API - -### parse(jsonc: string): any - -Parses a JSON-C string into the value defined by the content. \ No newline at end of file diff --git a/packages/kbn-kibana-manifest-parser/README.mdx b/packages/kbn-kibana-manifest-parser/README.mdx deleted file mode 100644 index 52467e94cdcecb..00000000000000 --- a/packages/kbn-kibana-manifest-parser/README.mdx +++ /dev/null @@ -1,24 +0,0 @@ ---- -id: kibDevDocsOpsKibanaManifestParser -slug: /kibana-dev-docs/ops/kibana-manifest-parser -title: "@kbn/kibana-manifest-parser" -description: A package for parsing Kibana package manifest files -date: 2022-05-24 -tags: ['kibana', 'dev', 'contributor', 'operations', 'package', 'kibana.json', 'kibana.jsonc'] ---- - -This package exposes functions and types for parsing Kibana manifest files (in the new `kibana.jsonc` format) - -## API - -### `parseKibanaManifest(jsonc: string): KibanaPackageManifest` - -Parses a JSON-C string into a valid `KibanaPackageManifest` object. If the manifest is invalid an error is thrown. - -### `readKibanaManifest(path: string): KibanaPackageManifest` - -Read a Kibana manifest from disk and parse it, returning a KibanaPackageManifest. If the file doesn't exist or is invalid in some way an error is thrown. - -### `validateKibanaManifest(value: unknown): KibanaPackageManifest` - -Validate a parsed Kibana manifest. If the manifest is invalid an error is thrown. diff --git a/packages/kbn-kibana-manifest-parser/src/kibana_manifest.ts b/packages/kbn-kibana-manifest-parser/src/kibana_manifest.ts deleted file mode 100644 index 2f99b0293d8a20..00000000000000 --- a/packages/kbn-kibana-manifest-parser/src/kibana_manifest.ts +++ /dev/null @@ -1,52 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -export type KibanaPackageType = - | 'plugin-browser' - | 'plugin-server' - | 'shared-browser' - | 'shared-server' - | 'shared-common' - | 'shared-scss' - | 'functional-tests' - | 'test-helper'; - -interface PackageManifestBaseFields { - type: KibanaPackageType; - id: string; - owner: string; - typeDeps: string[]; - runtimeDeps: string[]; -} - -export interface PluginPackageManifest extends PackageManifestBaseFields { - type: 'plugin-browser' | 'plugin-server'; - plugin: { - id: string; - configPath?: string[]; - requiredPlugins?: string[]; - optionalPlugins?: string[]; - description?: string; - enabledOnAnonymousPages?: boolean; - serviceFolders?: string[]; - }; -} - -export interface SharedBrowserPackageManifest extends PackageManifestBaseFields { - type: 'shared-browser' | 'shared-common'; - sharedBrowserBundle?: boolean; -} - -export interface BasePackageManifest extends PackageManifestBaseFields { - type: 'shared-server' | 'functional-tests' | 'test-helper' | 'shared-scss'; -} - -export type KibanaPackageManifest = - | PluginPackageManifest - | SharedBrowserPackageManifest - | BasePackageManifest; diff --git a/packages/kbn-kibana-manifest-parser/src/parse_kibana_manifest.test.ts b/packages/kbn-kibana-manifest-parser/src/parse_kibana_manifest.test.ts deleted file mode 100644 index 4743adb1f5e482..00000000000000 --- a/packages/kbn-kibana-manifest-parser/src/parse_kibana_manifest.test.ts +++ /dev/null @@ -1,229 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { validateKibanaManifest } from './parse_kibana_manifest'; - -const BASE_FIELDS = { - id: '@kbn/foo', - owner: '@elastic/kibana-operations', - typeDeps: [], - runtimeDeps: [], -}; - -describe('validateKibanaManifest', () => { - it('requires valid type', () => { - expect(() => validateKibanaManifest({})).toThrowErrorMatchingInlineSnapshot( - `"invalid package \\"type\\", options are [functional-tests, plugin-browser, plugin-server, shared-browser, shared-common, shared-server, test-helper, shared-scss]"` - ); - }); - - it('requires valid id', () => { - expect(() => - validateKibanaManifest({ - type: 'plugin-browser', - }) - ).toThrowErrorMatchingInlineSnapshot( - `"invalid package \\"id\\", must be a string that starts with @kbn/"` - ); - }); - - it('requires valid owner', () => { - expect(() => - validateKibanaManifest({ - type: 'plugin-browser', - id: '@kbn/foo', - }) - ).toThrowErrorMatchingInlineSnapshot( - `"invalid package \\"owner\\", must be a valid Github team handle starting with @"` - ); - }); - - it('requires valid typeDeps', () => { - expect(() => - validateKibanaManifest({ - type: 'plugin-browser', - id: '@kbn/foo', - owner: '@elastic/kibana-operations', - }) - ).toThrowErrorMatchingInlineSnapshot(`"invalid \\"typeDeps\\", must be an array of strings"`); - - expect(() => - validateKibanaManifest({ - type: 'plugin-browser', - id: '@kbn/foo', - owner: '@elastic/kibana-operations', - typeDeps: false, - }) - ).toThrowErrorMatchingInlineSnapshot(`"invalid \\"typeDeps\\", must be an array of strings"`); - - expect(() => - validateKibanaManifest({ - type: 'plugin-browser', - id: '@kbn/foo', - owner: '@elastic/kibana-operations', - typeDeps: [1], - }) - ).toThrowErrorMatchingInlineSnapshot(`"invalid \\"typeDeps\\", must be an array of strings"`); - }); - - it('requires valid runtimeDeps', () => { - expect(() => - validateKibanaManifest({ - type: 'plugin-browser', - id: '@kbn/foo', - owner: '@elastic/kibana-operations', - typeDeps: [], - }) - ).toThrowErrorMatchingInlineSnapshot( - `"invalid \\"runtimeDeps\\", must be an array of strings"` - ); - - expect(() => - validateKibanaManifest({ - type: 'plugin-browser', - id: '@kbn/foo', - owner: '@elastic/kibana-operations', - typeDeps: [], - runtimeDeps: false, - }) - ).toThrowErrorMatchingInlineSnapshot( - `"invalid \\"runtimeDeps\\", must be an array of strings"` - ); - - expect(() => - validateKibanaManifest({ - type: 'plugin-browser', - id: '@kbn/foo', - owner: '@elastic/kibana-operations', - typeDeps: [], - runtimeDeps: [1], - }) - ).toThrowErrorMatchingInlineSnapshot( - `"invalid \\"runtimeDeps\\", must be an array of strings"` - ); - }); - - it('validates base types', () => { - expect( - validateKibanaManifest({ - type: 'shared-server', - ...BASE_FIELDS, - }) - ).toMatchInlineSnapshot(` - Object { - "id": "@kbn/foo", - "owner": "@elastic/kibana-operations", - "runtimeDeps": Array [], - "type": "shared-server", - "typeDeps": Array [], - } - `); - expect( - validateKibanaManifest({ - type: 'functional-tests', - ...BASE_FIELDS, - }) - ).toMatchInlineSnapshot(` - Object { - "id": "@kbn/foo", - "owner": "@elastic/kibana-operations", - "runtimeDeps": Array [], - "type": "functional-tests", - "typeDeps": Array [], - } - `); - expect( - validateKibanaManifest({ - type: 'test-helper', - ...BASE_FIELDS, - }) - ).toMatchInlineSnapshot(` - Object { - "id": "@kbn/foo", - "owner": "@elastic/kibana-operations", - "runtimeDeps": Array [], - "type": "test-helper", - "typeDeps": Array [], - } - `); - }); - - describe('plugin-* types', () => { - it('requires valid plugin for plugin-* types', () => { - expect(() => - validateKibanaManifest({ - type: 'plugin-browser', - id: '@kbn/foo', - owner: '@elastic/kibana-operations', - typeDeps: [], - runtimeDeps: [], - }) - ).toThrowErrorMatchingInlineSnapshot(`"invalid package \\"plugin\\", must be an object"`); - }); - - it('requires "id" in plugins', () => { - expect(() => - validateKibanaManifest({ - type: 'plugin-browser', - id: '@kbn/foo', - owner: '@elastic/kibana-operations', - typeDeps: [], - runtimeDeps: [], - plugin: {}, - }) - ).toThrowErrorMatchingInlineSnapshot( - `"invalid \\"plugin.id\\", must be a string in camel or snake case"` - ); - - expect(() => - validateKibanaManifest({ - type: 'plugin-browser', - id: '@kbn/foo', - owner: '@elastic/kibana-operations', - typeDeps: [], - runtimeDeps: [], - plugin: { - id: 'not-camel-case', - }, - }) - ).toThrowErrorMatchingInlineSnapshot( - `"invalid \\"plugin.id\\", must be a string in camel or snake case"` - ); - - expect( - validateKibanaManifest({ - type: 'plugin-browser', - id: '@kbn/foo', - owner: '@elastic/kibana-operations', - typeDeps: [], - runtimeDeps: [], - plugin: { - id: 'camelCase', - }, - }) - ).toMatchInlineSnapshot(` - Object { - "id": "@kbn/foo", - "owner": "@elastic/kibana-operations", - "plugin": Object { - "configPath": undefined, - "description": undefined, - "enabledOnAnonymousPages": undefined, - "id": "camelCase", - "optionalPlugins": undefined, - "requiredPlugins": undefined, - "serviceFolders": undefined, - }, - "runtimeDeps": Array [], - "type": "plugin-browser", - "typeDeps": Array [], - } - `); - }); - }); -}); diff --git a/packages/kbn-kibana-manifest-parser/src/parse_kibana_manifest.ts b/packages/kbn-kibana-manifest-parser/src/parse_kibana_manifest.ts deleted file mode 100644 index aeccd08e6d8c0f..00000000000000 --- a/packages/kbn-kibana-manifest-parser/src/parse_kibana_manifest.ts +++ /dev/null @@ -1,189 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import Fs from 'fs'; - -import { parse } from '@kbn/jsonc'; -import { PluginPackageManifest, KibanaPackageManifest } from './kibana_manifest'; - -import { - isObj, - isValidId, - isValidPkgType, - isArrOfIds, - isArrOfStrings, - PACKAGE_TYPES, -} from './util'; - -const err = (msg: string) => new Error(msg); - -function validateKibanaManifestPlugin(plugin: unknown): PluginPackageManifest['plugin'] { - if (!isObj(plugin)) { - throw err(`invalid package "plugin", must be an object`); - } - - const { - id, - configPath, - requiredPlugins, - optionalPlugins, - description, - enabledOnAnonymousPages, - serviceFolders, - ...extra - } = plugin; - - const extraKeys = Object.keys(extra); - if (extraKeys.length) { - throw err(`unexpected keys in "plugin" of package [${extraKeys.join(', ')}]`); - } - - if (typeof id !== 'string' || !isValidId(id)) { - throw err(`invalid "plugin.id", must be a string in camel or snake case`); - } - - if (configPath !== undefined && !isArrOfIds(configPath)) { - throw err(`invalid "plugin.configPath", must be an array of strings in camel or snake case`); - } - - if (requiredPlugins !== undefined && !isArrOfIds(requiredPlugins)) { - throw err( - `invalid "plugin.requiredPlugins", must be an array of strings in camel or snake case` - ); - } - - if (optionalPlugins !== undefined && !isArrOfIds(optionalPlugins)) { - throw err( - `invalid "plugin.requiredPlugins", must be an array of strings in camel or snake case` - ); - } - - if (description !== undefined && typeof description !== 'string') { - throw err(`invalid "plugin.description", must be a string`); - } - - if (enabledOnAnonymousPages !== undefined && typeof enabledOnAnonymousPages !== 'boolean') { - throw err(`invalid "plugin.enabledOnAnonymousPages", must be a boolean`); - } - - if (serviceFolders !== undefined && !isArrOfStrings(serviceFolders)) { - throw err(`invalid "plugin.serviceFolders", must be an array of strings`); - } - - return { - id, - configPath, - requiredPlugins, - optionalPlugins, - description, - enabledOnAnonymousPages, - serviceFolders, - }; -} - -/** - * Validate the contents of a parsed kibana.jsonc file. - */ -export function validateKibanaManifest(parsed: unknown): KibanaPackageManifest { - if (!isObj(parsed)) { - throw err('expected root value to be an object'); - } - - const { type, id, owner, typeDeps, runtimeDeps, plugin, sharedBrowserBundle, ...extra } = parsed; - - const extraKeys = Object.keys(extra); - if (extraKeys.length) { - throw err(`unexpected keys in package manifest [${extraKeys.join(', ')}]`); - } - - if (!isValidPkgType(type)) { - throw err(`invalid package "type", options are [${PACKAGE_TYPES.join(', ')}]`); - } - - if (typeof id !== 'string' || !id.startsWith('@kbn/')) { - throw err(`invalid package "id", must be a string that starts with @kbn/`); - } - - if (typeof owner !== 'string' || !owner.startsWith('@')) { - throw err(`invalid package "owner", must be a valid Github team handle starting with @`); - } - - if (!isArrOfStrings(typeDeps)) { - throw err(`invalid "typeDeps", must be an array of strings`); - } - - if (!isArrOfStrings(runtimeDeps)) { - throw err(`invalid "runtimeDeps", must be an array of strings`); - } - - const base = { - id, - owner, - typeDeps, - runtimeDeps, - }; - - // return if this is one of the more basic types of package types - if (type === 'shared-server' || type === 'functional-tests' || type === 'test-helper') { - return { - type, - ...base, - }; - } - - // handle the plugin field for plugin-* types - if (type === 'plugin-browser' || type === 'plugin-server') { - return { - type, - ...base, - plugin: validateKibanaManifestPlugin(plugin), - }; - } - - // parse the sharedBrowserBundle for shared-browser and shared-common types - if (sharedBrowserBundle !== undefined && typeof sharedBrowserBundle !== 'boolean') { - throw err(`invalid "sharedBrowserBundle" field, expected undefined or a boolean`); - } - return { - type, - ...base, - sharedBrowserBundle, - }; -} - -/** - * Parse a kibana.jsonc file from the filesystem - */ -export function readKibanaManifest(path: string) { - let content; - try { - content = Fs.readFileSync(path, 'utf8'); - } catch (error) { - if (error.code === 'ENOENT') { - throw err(`Missing kibana.json file at ${path}`); - } - - throw error; - } - - return parseKibanaManifest(content); -} - -/** - * Parse a kibana.jsonc file from a string - */ -export function parseKibanaManifest(content: string) { - let parsed; - try { - parsed = parse(content); - } catch (error) { - throw err(`Invalid JSONc: ${error.message}`); - } - - return validateKibanaManifest(parsed); -} diff --git a/packages/kbn-kibana-manifest-parser/src/util.ts b/packages/kbn-kibana-manifest-parser/src/util.ts deleted file mode 100644 index 07b6a6c40a91e6..00000000000000 --- a/packages/kbn-kibana-manifest-parser/src/util.ts +++ /dev/null @@ -1,44 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { KibanaPackageType } from './kibana_manifest'; - -export const ID_PATTERN = /^[a-z][a-zA-Z_]*$/; - -export function isObj(v: unknown): v is Record { - return typeof v === 'object' && v !== null; -} - -export const isArrOfStrings = (v: unknown): v is string[] => - Array.isArray(v) && v.every((i) => typeof i === 'string'); - -export const isValidId = (id: string) => ID_PATTERN.test(id); - -export const isArrOfIds = (v: unknown): v is string[] => isArrOfStrings(v) && v.every(isValidId); - -/** - * This weird map allows us to ensure that every value in the - * `KibanaPackageType` union is represented because the mapped - * type requires that the `PACKAGE_TYPE_MAP` map has a property - * matching every value in the union. - */ -const PACKAGE_TYPE_MAP: { [k in KibanaPackageType]: true } = { - 'functional-tests': true, - 'plugin-browser': true, - 'plugin-server': true, - 'shared-browser': true, - 'shared-common': true, - 'shared-server': true, - 'test-helper': true, - 'shared-scss': true, -}; - -export const PACKAGE_TYPES = Object.keys(PACKAGE_TYPE_MAP) as KibanaPackageType[]; - -export const isValidPkgType = (type: unknown): type is keyof typeof PACKAGE_TYPE_MAP => - typeof type === 'string' && Object.hasOwn(PACKAGE_TYPE_MAP, type); diff --git a/packages/kbn-kibana-manifest-schema/README.mdx b/packages/kbn-kibana-manifest-schema/README.mdx index 96def9e65ee73a..176c960d49d82c 100644 --- a/packages/kbn-kibana-manifest-schema/README.mdx +++ b/packages/kbn-kibana-manifest-schema/README.mdx @@ -1,7 +1,7 @@ --- id: kibDevDocsOpsKibanaManifestSchema slug: /kibana-dev-docs/ops/kibana-manifest-schema -title: "@kbn/jsonc" +title: "@kbn/kibana-manifest-schema" description: The JSON schema for Kibana manifest files date: 2022-05-24 tags: ['kibana', 'dev', 'contributor', 'operations', 'json', 'schema', 'manifest'] diff --git a/packages/kbn-kibana-manifest-schema/kibana.jsonc b/packages/kbn-kibana-manifest-schema/kibana.jsonc new file mode 100644 index 00000000000000..5ddba1f9529a75 --- /dev/null +++ b/packages/kbn-kibana-manifest-schema/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/kibana-manifest-schema", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-kibana-manifest-schema/src/kibana_json_v2_schema.ts b/packages/kbn-kibana-manifest-schema/src/kibana_json_v2_schema.ts index ca02e48f00e2da..b6658088371210 100644 --- a/packages/kbn-kibana-manifest-schema/src/kibana_json_v2_schema.ts +++ b/packages/kbn-kibana-manifest-schema/src/kibana_json_v2_schema.ts @@ -13,11 +13,18 @@ export const PLUGIN_ID_PATTERN = /^[a-z][a-zA-Z_]*$/; export const MANIFEST_V2: JSONSchema = { type: 'object', - required: ['id', 'type', 'owner', 'typeDependencies', 'runtimeDependencies'], + required: ['id', 'type', 'owner', 'typeDeps', 'runtimeDeps'], + // @ts-expect-error VSCode specific JSONSchema extension + allowTrailingCommas: true, properties: { id: { type: 'string', pattern: '^@kbn/', + description: desc` + Module ID for this package. This must be globbally unique amoungst all + packages and should include the most important information about how this + package should be used. Avoid generic names to aid in disambiguation. + `, }, owner: { type: 'string', @@ -25,12 +32,11 @@ export const MANIFEST_V2: JSONSchema = { Github handle for the person or team who is responsible for this package. This owner will be used in the codeowners files for this package. - For additional codeowners, you add additional entries at the end of the - codeowners file. + For additional codeowners, you add manually add entries to the codeowners file. `, pattern: '^@', }, - typeDependencies: { + typeDeps: { type: 'array', description: desc` Packages which are required for the source code in the package to be @@ -40,7 +46,7 @@ export const MANIFEST_V2: JSONSchema = { type: 'string', }, }, - runtimeDependencies: { + runtimeDeps: { type: 'array', description: desc` Packages which are required for the source code in the package to run. This list @@ -50,6 +56,14 @@ export const MANIFEST_V2: JSONSchema = { type: 'string', }, }, + devOnly: { + type: 'boolean', + description: desc` + A devOnly package can be used by other devOnly packages and only by other devOnly + packages and will never be included in the distributable. + `, + default: false, + }, }, oneOf: [ { diff --git a/packages/kbn-logging-mocks/kibana.jsonc b/packages/kbn-logging-mocks/kibana.jsonc new file mode 100644 index 00000000000000..6b95f3a750f28b --- /dev/null +++ b/packages/kbn-logging-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/logging-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-logging/kibana.jsonc b/packages/kbn-logging/kibana.jsonc new file mode 100644 index 00000000000000..ab4df8442093bf --- /dev/null +++ b/packages/kbn-logging/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/logging", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-managed-vscode-config-cli/kibana.jsonc b/packages/kbn-managed-vscode-config-cli/kibana.jsonc new file mode 100644 index 00000000000000..1cbb5cb7ce7cbc --- /dev/null +++ b/packages/kbn-managed-vscode-config-cli/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/managed-vscode-config-cli", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-managed-vscode-config-cli/package.json b/packages/kbn-managed-vscode-config-cli/package.json index c1da1e53dbc041..ba4086c773eee3 100644 --- a/packages/kbn-managed-vscode-config-cli/package.json +++ b/packages/kbn-managed-vscode-config-cli/package.json @@ -3,8 +3,5 @@ "private": true, "version": "1.0.0", "main": "./target_node/index.js", - "license": "SSPL-1.0 OR Elastic License 2.0", - "kibana": { - "devOnly": true - } + "license": "SSPL-1.0 OR Elastic License 2.0" } diff --git a/packages/kbn-managed-vscode-config/kibana.jsonc b/packages/kbn-managed-vscode-config/kibana.jsonc new file mode 100644 index 00000000000000..c973127eb5485c --- /dev/null +++ b/packages/kbn-managed-vscode-config/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/managed-vscode-config", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-managed-vscode-config/package.json b/packages/kbn-managed-vscode-config/package.json index 84de677b6f3787..cc337813a73002 100644 --- a/packages/kbn-managed-vscode-config/package.json +++ b/packages/kbn-managed-vscode-config/package.json @@ -3,8 +3,5 @@ "private": true, "version": "1.0.0", "main": "./target_node/index.js", - "license": "SSPL-1.0 OR Elastic License 2.0", - "kibana": { - "devOnly": true - } + "license": "SSPL-1.0 OR Elastic License 2.0" } diff --git a/packages/kbn-mapbox-gl/kibana.jsonc b/packages/kbn-mapbox-gl/kibana.jsonc new file mode 100644 index 00000000000000..35ffb25b0b1150 --- /dev/null +++ b/packages/kbn-mapbox-gl/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/mapbox-gl", + "owner": "@elastic/kibana-gis", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-monaco/kibana.jsonc b/packages/kbn-monaco/kibana.jsonc new file mode 100644 index 00000000000000..42524f21bd5422 --- /dev/null +++ b/packages/kbn-monaco/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/monaco", + "owner": "@elastic/kibana-app-services", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-optimizer-webpack-helpers/kibana.jsonc b/packages/kbn-optimizer-webpack-helpers/kibana.jsonc new file mode 100644 index 00000000000000..102818ed032c21 --- /dev/null +++ b/packages/kbn-optimizer-webpack-helpers/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/optimizer-webpack-helpers", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-optimizer-webpack-helpers/package.json b/packages/kbn-optimizer-webpack-helpers/package.json index ca65edcf9d017d..a37b5ba48ee480 100644 --- a/packages/kbn-optimizer-webpack-helpers/package.json +++ b/packages/kbn-optimizer-webpack-helpers/package.json @@ -3,8 +3,5 @@ "private": true, "version": "1.0.0", "main": "./target_node/index.js", - "license": "SSPL-1.0 OR Elastic License 2.0", - "kibana": { - "devOnly": true - } + "license": "SSPL-1.0 OR Elastic License 2.0" } diff --git a/packages/kbn-optimizer/kibana.jsonc b/packages/kbn-optimizer/kibana.jsonc new file mode 100644 index 00000000000000..945fdc1e0366ca --- /dev/null +++ b/packages/kbn-optimizer/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/optimizer", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-optimizer/limits.yml b/packages/kbn-optimizer/limits.yml index 71abf16bb8fcd2..511d230ec968dd 100644 --- a/packages/kbn-optimizer/limits.yml +++ b/packages/kbn-optimizer/limits.yml @@ -1,23 +1,56 @@ pageLoadAssetSize: - advancedSettings: 27596 actions: 20000 + advancedSettings: 27596 aiops: 10000 alerting: 106936 apm: 64385 + banners: 17946 + bfetch: 22837 canvas: 1066647 + cases: 144442 charts: 55000 cloud: 21076 + cloudSecurityPosture: 19109 console: 46091 + controls: 40000 core: 435325 crossClusterReplication: 65408 + customIntegrations: 28810 dashboard: 82025 dashboardEnhanced: 65646 + data: 454087 + dataViewEditor: 12000 + dataViewFieldEditor: 27000 + dataViewManagement: 5000 + dataViews: 44532 + dataVisualizer: 27530 devTools: 38637 discover: 99999 discoverEnhanced: 42730 + embeddable: 87309 + embeddableEnhanced: 22107 enterpriseSearch: 35741 esUiShared: 326654 + eventAnnotation: 19334 + expressionError: 22127 + expressionGauge: 25000 + expressionHeatmap: 27505 + expressionImage: 19288 + expressionLegacyMetricVis: 23121 + expressionMetric: 22238 + expressionMetricVis: 23121 + expressionPartitionVis: 26338 + expressionRepeatImage: 22341 + expressionRevealImage: 25675 + expressions: 140958 + expressionShape: 34008 + expressionTagcloud: 27505 + expressionXY: 38000 features: 21723 + fieldFormats: 65209 + files: 22673 + fileUpload: 25664 + fleet: 126917 globalSearch: 29696 globalSearchBar: 50403 globalSearchProviders: 25554 @@ -27,11 +60,15 @@ pageLoadAssetSize: indexLifecycleManagement: 107090 indexManagement: 140608 infra: 184320 - fleet: 126917 ingestPipelines: 58003 inputControlVis: 172675 inspector: 148711 + interactiveSetup: 80000 kibanaOverview: 56279 + kibanaReact: 74422 + kibanaUsageCollection: 16463 + kibanaUtils: 79713 + kubernetesSecurity: 77234 lens: 36000 licenseManagement: 41817 licensing: 29004 @@ -39,31 +76,57 @@ pageLoadAssetSize: logstash: 53548 management: 46112 maps: 90000 + mapsEms: 26072 ml: 82187 monitoring: 80000 navigation: 37269 newsfeed: 42228 observability: 95000 + osquery: 107090 painlessLab: 179748 + presentationUtil: 58834 remoteClusters: 51327 + reporting: 57003 rollup: 97204 + runtimeFields: 41752 savedObjects: 108518 + savedObjectsFinder: 21691 savedObjectsManagement: 101836 savedObjectsTagging: 59482 savedObjectsTaggingOss: 20590 + savedSearch: 16225 + screenshotMode: 17856 + screenshotting: 22870 searchprofiler: 67080 security: 65433 + securitySolution: 273763 + sessionView: 77750 + share: 71239 snapshotRestore: 79032 spaces: 57868 + stackAlerts: 29684 + synthetics: 40958 telemetry: 51957 telemetryManagementSection: 38586 + threatIntelligence: 29195 + timelines: 327300 transform: 41007 triggersActionsUi: 119000 + uiActions: 35121 + uiActionsEnhanced: 38494 + unifiedFieldList: 65500 + unifiedSearch: 71059 upgradeAssistant: 81241 + urlDrilldown: 30063 urlForwarding: 32579 usageCollection: 39762 + ux: 20784 visDefaultEditor: 50178 + visTypeGauge: 24113 + visTypeHeatmap: 25340 visTypeMarkdown: 30896 + visTypeMetric: 23332 + visTypePie: 35583 visTypeTable: 94934 visTypeTagcloud: 37575 visTypeTimelion: 68883 @@ -73,66 +136,3 @@ pageLoadAssetSize: visTypeXy: 30000 visualizations: 90000 watcher: 43598 - runtimeFields: 41752 - stackAlerts: 29684 - presentationUtil: 58834 - osquery: 107090 - fileUpload: 25664 - dataVisualizer: 27530 - banners: 17946 - mapsEms: 26072 - timelines: 327300 - screenshotMode: 17856 - visTypePie: 35583 - expressionRevealImage: 25675 - cases: 144442 - expressionError: 22127 - expressionRepeatImage: 22341 - expressionImage: 19288 - expressionMetric: 22238 - expressionShape: 34008 - interactiveSetup: 80000 - expressionTagcloud: 27505 - securitySolution: 273763 - customIntegrations: 28810 - expressionMetricVis: 23121 - expressionLegacyMetricVis: 23121 - expressionHeatmap: 27505 - visTypeMetric: 23332 - bfetch: 22837 - kibanaUtils: 79713 - dataViews: 44532 - expressions: 140958 - fieldFormats: 65209 - kibanaReact: 74422 - share: 71239 - uiActions: 35121 - embeddable: 87309 - embeddableEnhanced: 22107 - uiActionsEnhanced: 38494 - urlDrilldown: 30063 - dataViewEditor: 12000 - dataViewFieldEditor: 27000 - dataViewManagement: 5000 - reporting: 57003 - visTypeHeatmap: 25340 - expressionGauge: 25000 - controls: 40000 - expressionPartitionVis: 26338 - savedSearch: 16225 - ux: 20784 - sessionView: 77750 - cloudSecurityPosture: 19109 - visTypeGauge: 24113 - unifiedSearch: 71059 - unifiedFieldList: 65500 - data: 454087 - eventAnnotation: 19334 - screenshotting: 22870 - synthetics: 40958 - expressionXY: 36000 - kibanaUsageCollection: 16463 - kubernetesSecurity: 77234 - threatIntelligence: 29195 - files: 22673 - savedObjectsFinder: 21691 diff --git a/packages/kbn-optimizer/package.json b/packages/kbn-optimizer/package.json index 4d3d17c5242c6e..a7d8a509276341 100644 --- a/packages/kbn-optimizer/package.json +++ b/packages/kbn-optimizer/package.json @@ -3,8 +3,5 @@ "version": "1.0.0", "private": true, "license": "SSPL-1.0 OR Elastic License 2.0", - "main": "./target_node/index.js", - "kibana": { - "devOnly": true - } + "main": "./target_node/index.js" } \ No newline at end of file diff --git a/packages/kbn-optimizer/src/cli.ts b/packages/kbn-optimizer/src/cli.ts index 449c58fdee2182..974bd4dbbcbc02 100644 --- a/packages/kbn-optimizer/src/cli.ts +++ b/packages/kbn-optimizer/src/cli.ts @@ -168,7 +168,7 @@ export function runKbnOptimizerCli(options: { defaultLimitsPath: string }) { updateBundleLimits({ log, config, - dropMissing: !(focus || filter), + dropMissing: !(focus.length || filter.length), limitsPath, }); } diff --git a/packages/kbn-optimizer/src/limits.ts b/packages/kbn-optimizer/src/limits.ts index bd7ed501d3a5ff..e4d3d24feeff95 100644 --- a/packages/kbn-optimizer/src/limits.ts +++ b/packages/kbn-optimizer/src/limits.ts @@ -71,6 +71,28 @@ export function validateLimitsForAllBundles( ); } + const sorted = limitBundleIds + .slice() + .sort((a, b) => a.localeCompare(b)) + .every((key, i) => limitBundleIds[i] === key); + if (!sorted) { + throw createFailError( + dedent` + The limits defined in packages/kbn-optimizer/limits.yml are not sorted correctly. To make + sure the file is automatically updatedable without dozens of extra changes, the keys in this + file must be sorted. + + Please sort the keys alphabetically or, to automatically update the limits file locally run: + + node scripts/build_kibana_platform_plugins.js --update-limits + + To validate your changes locally run: + + node scripts/build_kibana_platform_plugins.js --validate-limits + ` + '\n' + ); + } + log.success('limits.yml file valid'); } diff --git a/packages/kbn-performance-testing-dataset-extractor/kibana.jsonc b/packages/kbn-performance-testing-dataset-extractor/kibana.jsonc new file mode 100644 index 00000000000000..f09d991b49ec1e --- /dev/null +++ b/packages/kbn-performance-testing-dataset-extractor/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/performance-testing-dataset-extractor", + "devOnly": true, + "owner": "@elastic/kibana-performance-testing", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-performance-testing-dataset-extractor/package.json b/packages/kbn-performance-testing-dataset-extractor/package.json index 4d637728b28de7..12073ed76f3eae 100644 --- a/packages/kbn-performance-testing-dataset-extractor/package.json +++ b/packages/kbn-performance-testing-dataset-extractor/package.json @@ -4,8 +4,5 @@ "private": true, "version": "1.0.0", "main": "./target_node/index.js", - "license": "SSPL-1.0 OR Elastic License 2.0", - "kibana": { - "devOnly": true - } + "license": "SSPL-1.0 OR Elastic License 2.0" } diff --git a/packages/kbn-plugin-discovery/kibana.jsonc b/packages/kbn-plugin-discovery/kibana.jsonc new file mode 100644 index 00000000000000..8e6ad8a0c35de3 --- /dev/null +++ b/packages/kbn-plugin-discovery/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/plugin-discovery", + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-plugin-generator/kibana.jsonc b/packages/kbn-plugin-generator/kibana.jsonc new file mode 100644 index 00000000000000..1045f43539324f --- /dev/null +++ b/packages/kbn-plugin-generator/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/plugin-generator", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-plugin-generator/package.json b/packages/kbn-plugin-generator/package.json index 0b6c11709b90e1..28b7e849ab3c16 100644 --- a/packages/kbn-plugin-generator/package.json +++ b/packages/kbn-plugin-generator/package.json @@ -3,8 +3,5 @@ "version": "1.0.0", "private": true, "license": "SSPL-1.0 OR Elastic License 2.0", - "main": "target_node/index.js", - "kibana": { - "devOnly": true - } + "main": "target_node/index.js" } \ No newline at end of file diff --git a/packages/kbn-plugin-helpers/kibana.jsonc b/packages/kbn-plugin-helpers/kibana.jsonc new file mode 100644 index 00000000000000..84a87720dab0cb --- /dev/null +++ b/packages/kbn-plugin-helpers/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/plugin-helpers", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-plugin-helpers/package.json b/packages/kbn-plugin-helpers/package.json index cac041762f739a..206b3e77b39af7 100644 --- a/packages/kbn-plugin-helpers/package.json +++ b/packages/kbn-plugin-helpers/package.json @@ -4,9 +4,6 @@ "private": true, "description": "Just some helpers for kibana plugin devs.", "license": "SSPL-1.0 OR Elastic License 2.0", - "kibana": { - "devOnly": true - }, "main": "target_node/index.js", "bin": { "plugin-helpers": "bin/plugin-helpers.js" diff --git a/packages/kbn-react-field/kibana.jsonc b/packages/kbn-react-field/kibana.jsonc new file mode 100644 index 00000000000000..aade3b02429745 --- /dev/null +++ b/packages/kbn-react-field/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/react-field", + "owner": "@elastic/kibana-app-services", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-repo-source-classifier-cli/kibana.jsonc b/packages/kbn-repo-source-classifier-cli/kibana.jsonc new file mode 100644 index 00000000000000..a93259974364ad --- /dev/null +++ b/packages/kbn-repo-source-classifier-cli/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/repo-source-classifier-cli", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-repo-source-classifier-cli/package.json b/packages/kbn-repo-source-classifier-cli/package.json index 47ca9f6598f93d..a8e0cea71bef64 100644 --- a/packages/kbn-repo-source-classifier-cli/package.json +++ b/packages/kbn-repo-source-classifier-cli/package.json @@ -3,8 +3,5 @@ "private": true, "version": "1.0.0", "main": "./target_node/index.js", - "license": "SSPL-1.0 OR Elastic License 2.0", - "kibana": { - "devOnly": true - } + "license": "SSPL-1.0 OR Elastic License 2.0" } diff --git a/packages/kbn-repo-source-classifier/kibana.jsonc b/packages/kbn-repo-source-classifier/kibana.jsonc new file mode 100644 index 00000000000000..edeb2d3c64a396 --- /dev/null +++ b/packages/kbn-repo-source-classifier/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/repo-source-classifier", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-repo-source-classifier/package.json b/packages/kbn-repo-source-classifier/package.json index fce2be1b056ede..a6f81d992b285d 100644 --- a/packages/kbn-repo-source-classifier/package.json +++ b/packages/kbn-repo-source-classifier/package.json @@ -3,8 +3,5 @@ "private": true, "version": "1.0.0", "main": "./target_node/index.js", - "license": "SSPL-1.0 OR Elastic License 2.0", - "kibana": { - "devOnly": true - } + "license": "SSPL-1.0 OR Elastic License 2.0" } diff --git a/packages/kbn-rule-data-utils/kibana.jsonc b/packages/kbn-rule-data-utils/kibana.jsonc new file mode 100644 index 00000000000000..0fe42f6cb6e3d2 --- /dev/null +++ b/packages/kbn-rule-data-utils/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/rule-data-utils", + "owner": "@elastic/apm-ui", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-safer-lodash-set/kibana.jsonc b/packages/kbn-safer-lodash-set/kibana.jsonc new file mode 100644 index 00000000000000..8d7c5dfbb6bb38 --- /dev/null +++ b/packages/kbn-safer-lodash-set/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/safer-lodash-set", + "owner": "@elastic/kibana-security", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-securitysolution-autocomplete/kibana.jsonc b/packages/kbn-securitysolution-autocomplete/kibana.jsonc new file mode 100644 index 00000000000000..fbf73ddf07fb44 --- /dev/null +++ b/packages/kbn-securitysolution-autocomplete/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/securitysolution-autocomplete", + "owner": "@elastic/security-solution-platform", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-securitysolution-es-utils/kibana.jsonc b/packages/kbn-securitysolution-es-utils/kibana.jsonc new file mode 100644 index 00000000000000..a798aefeae37d7 --- /dev/null +++ b/packages/kbn-securitysolution-es-utils/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/securitysolution-es-utils", + "owner": "@elastic/security-solution-platform", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-securitysolution-hook-utils/kibana.jsonc b/packages/kbn-securitysolution-hook-utils/kibana.jsonc new file mode 100644 index 00000000000000..cd7d23f07792d7 --- /dev/null +++ b/packages/kbn-securitysolution-hook-utils/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/securitysolution-hook-utils", + "owner": "@elastic/security-solution-platform", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/kibana.jsonc b/packages/kbn-securitysolution-io-ts-alerting-types/kibana.jsonc new file mode 100644 index 00000000000000..d1e730f414d188 --- /dev/null +++ b/packages/kbn-securitysolution-io-ts-alerting-types/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/securitysolution-io-ts-alerting-types", + "owner": "@elastic/security-solution-platform", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-securitysolution-io-ts-list-types/kibana.jsonc b/packages/kbn-securitysolution-io-ts-list-types/kibana.jsonc new file mode 100644 index 00000000000000..d50df0b0d6512d --- /dev/null +++ b/packages/kbn-securitysolution-io-ts-list-types/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/securitysolution-io-ts-list-types", + "owner": "@elastic/security-solution-platform", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/index.ts index 730c1f2cd491df..f7e533aa7d4cd0 100644 --- a/packages/kbn-securitysolution-io-ts-list-types/src/common/index.ts +++ b/packages/kbn-securitysolution-io-ts-list-types/src/common/index.ts @@ -47,6 +47,7 @@ export * from './os_type'; export * from './page'; export * from './per_page'; export * from './pit'; +export * from './search'; export * from './search_after'; export * from './serializer'; export * from './sort_field'; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/search/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/search/index.test.ts new file mode 100644 index 00000000000000..99d73fd5e059ac --- /dev/null +++ b/packages/kbn-securitysolution-io-ts-list-types/src/common/search/index.test.ts @@ -0,0 +1,56 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { exactCheck } from '@kbn/securitysolution-io-ts-utils'; +import { searchOrUndefined } from '.'; + +import * as t from 'io-ts'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { left } from 'fp-ts/lib/Either'; + +import { foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; + +describe('search', () => { + test('it will validate a correct search', () => { + const payload = 'name:foo'; + const decoded = searchOrUndefined.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it will validate with the value of "undefined"', () => { + const obj = t.exact( + t.type({ + search: searchOrUndefined, + }) + ); + const payload: t.TypeOf = { + search: undefined, + }; + const decoded = obj.decode({ + pit_id: undefined, + }); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + + test('it will fail to validate an incorrect search', () => { + const payload = ['foo']; + const decoded = searchOrUndefined.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([ + 'Invalid value "["foo"]" supplied to "(string | undefined)"', + ]); + expect(message.schema).toEqual({}); + }); +}); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/common/search/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/common/search/index.ts new file mode 100644 index 00000000000000..319c225edf0072 --- /dev/null +++ b/packages/kbn-securitysolution-io-ts-list-types/src/common/search/index.ts @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import * as t from 'io-ts'; + +export const search = t.string; +export type Search = t.TypeOf; + +export const searchOrUndefined = t.union([search, t.undefined]); +export type SearchOrUndefined = t.TypeOf; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_item_schema/index.mock.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_item_schema/index.mock.ts index 8f64dccf6d577b..4026d878ca2785 100644 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_item_schema/index.mock.ts +++ b/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_item_schema/index.mock.ts @@ -16,6 +16,7 @@ export const getFindExceptionListItemSchemaMock = (): FindExceptionListItemSchem namespace_type: NAMESPACE_TYPE, page: '1', per_page: '25', + search: undefined, sort_field: undefined, sort_order: undefined, }); @@ -26,6 +27,7 @@ export const getFindExceptionListItemSchemaMultipleMock = (): FindExceptionListI namespace_type: 'single,single,agnostic', page: '1', per_page: '25', + search: undefined, sort_field: undefined, sort_order: undefined, }); @@ -37,6 +39,7 @@ export const getFindExceptionListItemSchemaDecodedMock = namespace_type: [NAMESPACE_TYPE], page: 1, per_page: 25, + search: undefined, sort_field: undefined, sort_order: undefined, }); @@ -48,6 +51,7 @@ export const getFindExceptionListItemSchemaDecodedMultipleMock = namespace_type: ['single', 'single', 'agnostic'], page: 1, per_page: 25, + search: undefined, sort_field: undefined, sort_order: undefined, }); diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_item_schema/index.test.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_item_schema/index.test.ts index 04afee30c1ab3b..fab9111aa0eb05 100644 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_item_schema/index.test.ts +++ b/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_item_schema/index.test.ts @@ -55,6 +55,7 @@ describe('find_list_item_schema', () => { namespace_type: ['single'], page: undefined, per_page: undefined, + search: undefined, sort_field: undefined, sort_order: undefined, }; @@ -73,7 +74,7 @@ describe('find_list_item_schema', () => { expect(message.schema).toEqual(expected); }); - test('it should validate with pre_page missing', () => { + test('it should validate with per_page missing', () => { const payload = getFindExceptionListItemSchemaMock(); delete payload.per_page; const decoded = findExceptionListItemSchema.decode(payload); @@ -123,6 +124,18 @@ describe('find_list_item_schema', () => { expect(message.schema).toEqual(expected); }); + test('it should validate with search missing', () => { + const payload = getFindExceptionListItemSchemaMock(); + delete payload.search; + const decoded = findExceptionListItemSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + const expected = getFindExceptionListItemSchemaDecodedMock(); + delete expected.search; + expect(message.schema).toEqual(expected); + }); + test('it should not allow an extra key to be sent in', () => { const payload: FindExceptionListItemSchema & { extraKey: string; diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_item_schema/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_item_schema/index.ts index 88756ac0eb301a..0ca8140d048dcf 100644 --- a/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_item_schema/index.ts +++ b/packages/kbn-securitysolution-io-ts-list-types/src/request/find_exception_list_item_schema/index.ts @@ -21,6 +21,7 @@ import { import { RequiredKeepUndefined } from '../../common/required_keep_undefined'; import { sort_field } from '../../common/sort_field'; import { sort_order } from '../../common/sort_order'; +import { search } from '../../common/search'; export const findExceptionListItemSchema = t.intersection([ t.exact( @@ -34,6 +35,7 @@ export const findExceptionListItemSchema = t.intersection([ namespace_type: DefaultNamespaceArray, // defaults to ['single'] if not set during decode page: StringToPositiveNumber, // defaults to undefined if not set during decode per_page: StringToPositiveNumber, // defaults to undefined if not set during decode + search, sort_field, // defaults to undefined if not set during decode sort_order, // defaults to undefined if not set during decode }) diff --git a/packages/kbn-securitysolution-io-ts-list-types/src/typescript_types/index.ts b/packages/kbn-securitysolution-io-ts-list-types/src/typescript_types/index.ts index a5eb4f976debd5..b8f03629135a29 100644 --- a/packages/kbn-securitysolution-io-ts-list-types/src/typescript_types/index.ts +++ b/packages/kbn-securitysolution-io-ts-list-types/src/typescript_types/index.ts @@ -99,10 +99,10 @@ export interface ExceptionListIdentifiers { export interface ApiCallFindListsItemsMemoProps { lists: ExceptionListIdentifiers[]; - filterOptions: FilterExceptionsOptions[]; pagination: Partial; showDetectionsListsOnly: boolean; showEndpointListsOnly: boolean; + filter?: string; onError: (arg: string[]) => void; onSuccess: (arg: UseExceptionListItemsSuccess) => void; } @@ -168,8 +168,9 @@ export interface ApiCallByListIdProps { http: HttpStart; listIds: string[]; namespaceTypes: NamespaceType[]; - filterOptions: FilterExceptionsOptions[]; pagination: Partial; + search?: string; + filter?: string; signal: AbortSignal; } diff --git a/packages/kbn-securitysolution-io-ts-types/kibana.jsonc b/packages/kbn-securitysolution-io-ts-types/kibana.jsonc new file mode 100644 index 00000000000000..6ef8a21b00e1ee --- /dev/null +++ b/packages/kbn-securitysolution-io-ts-types/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/securitysolution-io-ts-types", + "owner": "@elastic/security-solution-platform", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-securitysolution-io-ts-utils/kibana.jsonc b/packages/kbn-securitysolution-io-ts-utils/kibana.jsonc new file mode 100644 index 00000000000000..2c86eea21c0c12 --- /dev/null +++ b/packages/kbn-securitysolution-io-ts-utils/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/securitysolution-io-ts-utils", + "owner": "@elastic/security-solution-platform", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-securitysolution-list-api/kibana.jsonc b/packages/kbn-securitysolution-list-api/kibana.jsonc new file mode 100644 index 00000000000000..b162805a8c8b4f --- /dev/null +++ b/packages/kbn-securitysolution-list-api/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/securitysolution-list-api", + "owner": "@elastic/security-solution-platform", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-securitysolution-list-api/src/api/index.ts b/packages/kbn-securitysolution-list-api/src/api/index.ts index a0361d044977cc..871987ff7d3678 100644 --- a/packages/kbn-securitysolution-list-api/src/api/index.ts +++ b/packages/kbn-securitysolution-list-api/src/api/index.ts @@ -34,8 +34,6 @@ import { import { ENDPOINT_LIST_URL, EXCEPTION_LIST_ITEM_URL, - EXCEPTION_LIST_NAMESPACE, - EXCEPTION_LIST_NAMESPACE_AGNOSTIC, EXCEPTION_LIST_URL, } from '@kbn/securitysolution-list-constants'; import { toError, toPromise } from '../fp_utils'; @@ -324,7 +322,8 @@ export { fetchExceptionListByIdWithValidation as fetchExceptionListById }; * @param http Kibana http service * @param listIds ExceptionList list_ids (not ID) * @param namespaceTypes ExceptionList namespace_types - * @param filterOptions optional - filter by field or tags + * @param search optional - simple search string + * @param filter optional * @param pagination optional * @param signal to cancel request * @@ -334,36 +333,20 @@ const fetchExceptionListsItemsByListIds = async ({ http, listIds, namespaceTypes, - filterOptions, + filter, pagination, + search, signal, }: ApiCallByListIdProps): Promise => { - const filters: string = filterOptions - .map((filter, index) => { - const namespace = namespaceTypes[index]; - const filterNamespace = - namespace === 'agnostic' ? EXCEPTION_LIST_NAMESPACE_AGNOSTIC : EXCEPTION_LIST_NAMESPACE; - const formattedFilters = [ - ...(filter.filter.length - ? [`${filterNamespace}.attributes.entries.field:${filter.filter}*`] - : []), - ...(filter.tags.length - ? filter.tags.map((t) => `${filterNamespace}.attributes.tags:${t}`) - : []), - ]; - - return formattedFilters.join(' AND '); - }) - .join(','); - const query = { list_id: listIds.join(','), namespace_type: namespaceTypes.join(','), page: pagination.page ? `${pagination.page}` : '1', per_page: pagination.perPage ? `${pagination.perPage}` : '20', + search, sort_field: 'exception-list.created_at', sort_order: 'desc', - ...(filters.trim() !== '' ? { filter: filters } : {}), + filter, }; return http.fetch(`${EXCEPTION_LIST_ITEM_URL}/_find`, { @@ -374,11 +357,12 @@ const fetchExceptionListsItemsByListIds = async ({ }; const fetchExceptionListsItemsByListIdsWithValidation = async ({ - filterOptions, + filter, http, listIds, namespaceTypes, pagination, + search, signal, }: ApiCallByListIdProps): Promise => flow( @@ -386,11 +370,12 @@ const fetchExceptionListsItemsByListIdsWithValidation = async ({ tryCatch( () => fetchExceptionListsItemsByListIds({ - filterOptions, + filter, http, listIds, namespaceTypes, pagination, + search, signal, }), toError diff --git a/packages/kbn-securitysolution-list-constants/kibana.jsonc b/packages/kbn-securitysolution-list-constants/kibana.jsonc new file mode 100644 index 00000000000000..ffe606ca6ade84 --- /dev/null +++ b/packages/kbn-securitysolution-list-constants/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/securitysolution-list-constants", + "owner": "@elastic/security-solution-platform", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-securitysolution-list-hooks/index.ts b/packages/kbn-securitysolution-list-hooks/index.ts index 4c523fe5772116..c2469bc4c49481 100644 --- a/packages/kbn-securitysolution-list-hooks/index.ts +++ b/packages/kbn-securitysolution-list-hooks/index.ts @@ -10,7 +10,6 @@ export * from './src/use_api'; export * from './src/use_create_list_index'; export * from './src/use_cursor'; export * from './src/use_delete_list'; -export * from './src/use_exception_list_items'; export * from './src/use_exception_lists'; export * from './src/use_export_list'; export * from './src/use_find_lists'; diff --git a/packages/kbn-securitysolution-list-hooks/kibana.jsonc b/packages/kbn-securitysolution-list-hooks/kibana.jsonc new file mode 100644 index 00000000000000..12d670f46ae326 --- /dev/null +++ b/packages/kbn-securitysolution-list-hooks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/securitysolution-list-hooks", + "owner": "@elastic/security-solution-platform", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-securitysolution-list-hooks/src/index.ts b/packages/kbn-securitysolution-list-hooks/src/index.ts new file mode 100644 index 00000000000000..e458abd0448ada --- /dev/null +++ b/packages/kbn-securitysolution-list-hooks/src/index.ts @@ -0,0 +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 + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ +export * from './transforms'; +export * from './use_api'; +export * from './use_create_list_index'; +export * from './use_cursor'; +export * from './use_delete_list'; +export * from './use_exception_lists'; +export * from './use_export_list'; +export * from './use_find_lists'; +export * from './use_import_list'; +export * from './use_persist_exception_item'; +export * from './use_persist_exception_list'; +export * from './use_read_list_index'; +export * from './use_read_list_privileges'; diff --git a/packages/kbn-securitysolution-list-hooks/src/use_api/index.ts b/packages/kbn-securitysolution-list-hooks/src/use_api/index.ts index 3b980f84d82a8f..ec76d169390ccc 100644 --- a/packages/kbn-securitysolution-list-hooks/src/use_api/index.ts +++ b/packages/kbn-securitysolution-list-hooks/src/use_api/index.ts @@ -170,7 +170,7 @@ export const useApi = (http: HttpStart): ExceptionsApi => { }, async getExceptionListsItems({ lists, - filterOptions, + filter, pagination, showDetectionsListsOnly, showEndpointListsOnly, @@ -192,7 +192,7 @@ export const useApi = (http: HttpStart): ExceptionsApi => { per_page: perPage, total, } = await Api.fetchExceptionListsItemsByListIds({ - filterOptions, + filter, http, listIds: ids, namespaceTypes: namespaces, diff --git a/packages/kbn-securitysolution-list-hooks/src/use_exception_list_items/index.test.ts b/packages/kbn-securitysolution-list-hooks/src/use_exception_list_items/index.test.ts deleted file mode 100644 index 4ca0a66e4f602b..00000000000000 --- a/packages/kbn-securitysolution-list-hooks/src/use_exception_list_items/index.test.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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -describe('useExceptionListItems', () => { - test('Tests should be ported', () => { - // TODO: Port all the tests from: x-pack/plugins/lists/public/exceptions/hooks/use_exception_list_items.test.ts here once mocks are figured out and kbn package mocks are figured out - expect(true).toBe(true); - }); -}); diff --git a/packages/kbn-securitysolution-list-hooks/src/use_exception_list_items/index.ts b/packages/kbn-securitysolution-list-hooks/src/use_exception_list_items/index.ts deleted file mode 100644 index 623e1e76a7f536..00000000000000 --- a/packages/kbn-securitysolution-list-hooks/src/use_exception_list_items/index.ts +++ /dev/null @@ -1,185 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { useEffect, useRef, useState } from 'react'; -import type { - ExceptionListItemSchema, - Pagination, - UseExceptionListProps, - FilterExceptionsOptions, -} from '@kbn/securitysolution-io-ts-list-types'; -import { fetchExceptionListsItemsByListIds } from '@kbn/securitysolution-list-api'; - -import { getIdsAndNamespaces } from '@kbn/securitysolution-list-utils'; -import { transformInput } from '../transforms'; - -type Func = () => void; -export type ReturnExceptionListAndItems = [ - boolean, - ExceptionListItemSchema[], - Pagination, - Func | null -]; - -/** - * Hook for using to get an ExceptionList and its ExceptionListItems - * - * @param http Kibana http service - * @param lists array of ExceptionListIdentifiers for all lists to fetch - * @param onError error callback - * @param onSuccess callback when all lists fetched successfully - * @param filterOptions optional - filter by fields or tags - * @param showDetectionsListsOnly boolean, if true, only detection lists are searched - * @param showEndpointListsOnly boolean, if true, only endpoint lists are searched - * @param matchFilters boolean, if true, applies first filter in filterOptions to - * all lists - * @param pagination optional - * - */ -export const useExceptionListItems = ({ - http, - lists, - pagination = { - page: 1, - perPage: 20, - total: 0, - }, - filterOptions, - showDetectionsListsOnly, - showEndpointListsOnly, - matchFilters, - onError, - onSuccess, -}: UseExceptionListProps): ReturnExceptionListAndItems => { - const [exceptionItems, setExceptionListItems] = useState([]); - const [paginationInfo, setPagination] = useState(pagination); - const fetchExceptionListsItems = useRef(null); - const [loading, setLoading] = useState(true); - const { ids, namespaces } = getIdsAndNamespaces({ - lists, - showDetection: showDetectionsListsOnly, - showEndpoint: showEndpointListsOnly, - }); - const filters: FilterExceptionsOptions[] = - matchFilters && filterOptions.length > 0 ? ids.map(() => filterOptions[0]) : filterOptions; - const idsAsString: string = ids.join(','); - const namespacesAsString: string = namespaces.join(','); - const filterAsString: string = filterOptions.map(({ filter }) => filter).join(','); - const filterTagsAsString: string = filterOptions.map(({ tags }) => tags.join(',')).join(','); - - useEffect( - () => { - let isSubscribed = true; - const abortCtrl = new AbortController(); - - const fetchData = async (): Promise => { - try { - setLoading(true); - - if (ids.length === 0 && isSubscribed) { - setPagination({ - page: 0, - perPage: pagination.perPage, - total: 0, - }); - setExceptionListItems([]); - - if (onSuccess != null) { - onSuccess({ - exceptions: [], - pagination: { - page: 0, - perPage: pagination.perPage, - total: 0, - }, - }); - } - setLoading(false); - } else { - const { - page, - per_page: perPage, - total, - data, - } = await fetchExceptionListsItemsByListIds({ - filterOptions: filters, - http, - listIds: ids, - namespaceTypes: namespaces, - pagination: { - page: pagination.page, - perPage: pagination.perPage, - }, - signal: abortCtrl.signal, - }); - - // Please see `x-pack/plugins/lists/public/exceptions/transforms.ts` doc notes - // for context around the temporary `id` - const transformedData = data.map((item) => transformInput(item)); - - if (isSubscribed) { - setPagination({ - page, - perPage, - total, - }); - setExceptionListItems(transformedData); - - if (onSuccess != null) { - onSuccess({ - exceptions: transformedData, - pagination: { - page, - perPage, - total, - }, - }); - } - } - } - } catch (error) { - if (isSubscribed) { - setExceptionListItems([]); - setPagination({ - page: 1, - perPage: 20, - total: 0, - }); - if (onError != null) { - onError(error); - } - } - } - - if (isSubscribed) { - setLoading(false); - } - }; - - fetchData(); - - fetchExceptionListsItems.current = fetchData; - return (): void => { - isSubscribed = false; - abortCtrl.abort(); - }; - }, // eslint-disable-next-line react-hooks/exhaustive-deps - [ - http, - idsAsString, - namespacesAsString, - setExceptionListItems, - pagination.page, - pagination.perPage, - filterAsString, - filterTagsAsString, - ] - ); - - return [loading, exceptionItems, paginationInfo, fetchExceptionListsItems.current]; -}; diff --git a/packages/kbn-securitysolution-list-utils/kibana.jsonc b/packages/kbn-securitysolution-list-utils/kibana.jsonc new file mode 100644 index 00000000000000..db7d0a5ec334f0 --- /dev/null +++ b/packages/kbn-securitysolution-list-utils/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/securitysolution-list-utils", + "owner": "@elastic/security-solution-platform", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-securitysolution-rules/kibana.jsonc b/packages/kbn-securitysolution-rules/kibana.jsonc new file mode 100644 index 00000000000000..b7e64cfd39e6b7 --- /dev/null +++ b/packages/kbn-securitysolution-rules/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/securitysolution-rules", + "owner": "@elastic/security-solution-platform", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-securitysolution-t-grid/kibana.jsonc b/packages/kbn-securitysolution-t-grid/kibana.jsonc new file mode 100644 index 00000000000000..bc0f533b721201 --- /dev/null +++ b/packages/kbn-securitysolution-t-grid/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/securitysolution-t-grid", + "owner": "@elastic/security-solution-platform", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-securitysolution-utils/kibana.jsonc b/packages/kbn-securitysolution-utils/kibana.jsonc new file mode 100644 index 00000000000000..24e63965c20c88 --- /dev/null +++ b/packages/kbn-securitysolution-utils/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/securitysolution-utils", + "owner": "@elastic/security-solution-platform", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-server-http-tools/kibana.jsonc b/packages/kbn-server-http-tools/kibana.jsonc new file mode 100644 index 00000000000000..b96916745c9847 --- /dev/null +++ b/packages/kbn-server-http-tools/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/server-http-tools", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-server-route-repository/kibana.jsonc b/packages/kbn-server-route-repository/kibana.jsonc new file mode 100644 index 00000000000000..e1e69049b1791f --- /dev/null +++ b/packages/kbn-server-route-repository/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/server-route-repository", + "owner": "@elastic/apm-ui", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-shared-svg/kibana.jsonc b/packages/kbn-shared-svg/kibana.jsonc new file mode 100644 index 00000000000000..e816819c9c24a9 --- /dev/null +++ b/packages/kbn-shared-svg/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/shared-svg", + "owner": "@elastic/apm-ui", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-shared-ux-utility/kibana.jsonc b/packages/kbn-shared-ux-utility/kibana.jsonc new file mode 100644 index 00000000000000..55c3996ae4dbcc --- /dev/null +++ b/packages/kbn-shared-ux-utility/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/shared-ux-utility", + "owner": "@elastic/shared-ux", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-some-dev-log/kibana.jsonc b/packages/kbn-some-dev-log/kibana.jsonc new file mode 100644 index 00000000000000..e39904defc5521 --- /dev/null +++ b/packages/kbn-some-dev-log/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/some-dev-log", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-some-dev-log/package.json b/packages/kbn-some-dev-log/package.json index f075d74b653597..9b01a43a03c003 100644 --- a/packages/kbn-some-dev-log/package.json +++ b/packages/kbn-some-dev-log/package.json @@ -3,8 +3,5 @@ "private": true, "version": "1.0.0", "main": "./target_node/index.js", - "license": "SSPL-1.0 OR Elastic License 2.0", - "kibana": { - "devOnly": true - } + "license": "SSPL-1.0 OR Elastic License 2.0" } diff --git a/packages/kbn-sort-package-json/kibana.jsonc b/packages/kbn-sort-package-json/kibana.jsonc new file mode 100644 index 00000000000000..72345c2ccd31c5 --- /dev/null +++ b/packages/kbn-sort-package-json/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/sort-package-json", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-sort-package-json/package.json b/packages/kbn-sort-package-json/package.json index 9a875835d74506..922124b1bdd73d 100644 --- a/packages/kbn-sort-package-json/package.json +++ b/packages/kbn-sort-package-json/package.json @@ -3,8 +3,5 @@ "private": true, "version": "1.0.0", "main": "./target_node/index.js", - "license": "SSPL-1.0 OR Elastic License 2.0", - "kibana": { - "devOnly": true - } + "license": "SSPL-1.0 OR Elastic License 2.0" } diff --git a/packages/kbn-spec-to-console/kibana.jsonc b/packages/kbn-spec-to-console/kibana.jsonc new file mode 100644 index 00000000000000..cf71c222f6f168 --- /dev/null +++ b/packages/kbn-spec-to-console/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/spec-to-console", + "devOnly": true, + "owner": "@elastic/platform-deployment-management", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-spec-to-console/package.json b/packages/kbn-spec-to-console/package.json index b4e488db7f4d95..b60df2a95ebb9e 100644 --- a/packages/kbn-spec-to-console/package.json +++ b/packages/kbn-spec-to-console/package.json @@ -12,9 +12,6 @@ }, "author": "", "license": "SSPL-1.0 OR Elastic License 2.0", - "kibana": { - "devOnly": true - }, "bugs": { "url": "https://github.com/jbudz/spec-to-console/issues" }, diff --git a/packages/kbn-std/kibana.jsonc b/packages/kbn-std/kibana.jsonc new file mode 100644 index 00000000000000..246c11ee7c3f19 --- /dev/null +++ b/packages/kbn-std/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/std", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-stdio-dev-helpers/kibana.jsonc b/packages/kbn-stdio-dev-helpers/kibana.jsonc new file mode 100644 index 00000000000000..0001ba53d7b7e6 --- /dev/null +++ b/packages/kbn-stdio-dev-helpers/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/stdio-dev-helpers", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-stdio-dev-helpers/package.json b/packages/kbn-stdio-dev-helpers/package.json index 23b0a1cf65a760..ac14acd56e729c 100644 --- a/packages/kbn-stdio-dev-helpers/package.json +++ b/packages/kbn-stdio-dev-helpers/package.json @@ -3,8 +3,5 @@ "private": true, "version": "1.0.0", "main": "./target_node/index.js", - "license": "SSPL-1.0 OR Elastic License 2.0", - "kibana": { - "devOnly": true - } + "license": "SSPL-1.0 OR Elastic License 2.0" } diff --git a/packages/kbn-storybook/kibana.jsonc b/packages/kbn-storybook/kibana.jsonc new file mode 100644 index 00000000000000..b5499440f46ad8 --- /dev/null +++ b/packages/kbn-storybook/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/storybook", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-storybook/package.json b/packages/kbn-storybook/package.json index f24d926aa42a30..162152c7f19220 100644 --- a/packages/kbn-storybook/package.json +++ b/packages/kbn-storybook/package.json @@ -4,8 +4,5 @@ "version": "1.0.0", "private": true, "license": "SSPL-1.0 OR Elastic License 2.0", - "main": "./target_node/index.js", - "kibana": { - "devOnly": true - } + "main": "./target_node/index.js" } \ No newline at end of file diff --git a/packages/kbn-synthetic-package-map/kibana.jsonc b/packages/kbn-synthetic-package-map/kibana.jsonc new file mode 100644 index 00000000000000..153b6548ce841c --- /dev/null +++ b/packages/kbn-synthetic-package-map/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/synthetic-package-map", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-synthetic-package-map/package.json b/packages/kbn-synthetic-package-map/package.json index ae209fdf98db08..ec6ac454bf31d8 100644 --- a/packages/kbn-synthetic-package-map/package.json +++ b/packages/kbn-synthetic-package-map/package.json @@ -3,8 +3,5 @@ "private": true, "version": "1.0.0", "main": "./index.js", - "license": "SSPL-1.0 OR Elastic License 2.0", - "kibana": { - "devOnly": true - } + "license": "SSPL-1.0 OR Elastic License 2.0" } diff --git a/packages/kbn-telemetry-tools/kibana.jsonc b/packages/kbn-telemetry-tools/kibana.jsonc new file mode 100644 index 00000000000000..c182ddd3e6960a --- /dev/null +++ b/packages/kbn-telemetry-tools/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/telemetry-tools", + "devOnly": true, + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-telemetry-tools/package.json b/packages/kbn-telemetry-tools/package.json index a0096f090e8307..649ff72a569565 100644 --- a/packages/kbn-telemetry-tools/package.json +++ b/packages/kbn-telemetry-tools/package.json @@ -4,8 +4,5 @@ "author": "Kibana Core", "license": "SSPL-1.0 OR Elastic License 2.0", "main": "./target_node/index.js", - "private": true, - "kibana": { - "devOnly": true - } + "private": true } \ No newline at end of file diff --git a/packages/kbn-test-jest-helpers/kibana.jsonc b/packages/kbn-test-jest-helpers/kibana.jsonc new file mode 100644 index 00000000000000..70750f8f4f28d1 --- /dev/null +++ b/packages/kbn-test-jest-helpers/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/test-jest-helpers", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-test-jest-helpers/package.json b/packages/kbn-test-jest-helpers/package.json index afab6001d605dd..fa5851895c6d0c 100644 --- a/packages/kbn-test-jest-helpers/package.json +++ b/packages/kbn-test-jest-helpers/package.json @@ -3,8 +3,5 @@ "version": "1.0.0", "private": true, "license": "SSPL-1.0 OR Elastic License 2.0", - "main": "./target_node", - "kibana": { - "devOnly": true - } + "main": "./target_node" } diff --git a/packages/kbn-test-subj-selector/kibana.jsonc b/packages/kbn-test-subj-selector/kibana.jsonc new file mode 100644 index 00000000000000..697ce5593ea716 --- /dev/null +++ b/packages/kbn-test-subj-selector/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/test-subj-selector", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-test-subj-selector/package.json b/packages/kbn-test-subj-selector/package.json index 875397d1ec7056..8ced36990a6e32 100755 --- a/packages/kbn-test-subj-selector/package.json +++ b/packages/kbn-test-subj-selector/package.json @@ -6,8 +6,5 @@ "keywords": [], "author": "Spencer Alger ", "license": "SSPL-1.0 OR Elastic License 2.0", - "private": "true", - "kibana": { - "devOnly": true - } + "private": "true" } diff --git a/packages/kbn-test/kibana.jsonc b/packages/kbn-test/kibana.jsonc new file mode 100644 index 00000000000000..c921f7ac396266 --- /dev/null +++ b/packages/kbn-test/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/test", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-test/package.json b/packages/kbn-test/package.json index 5f5e475e392c45..de6ba54c26800e 100644 --- a/packages/kbn-test/package.json +++ b/packages/kbn-test/package.json @@ -4,8 +4,5 @@ "version": "1.0.0", "private": true, "license": "SSPL-1.0 OR Elastic License 2.0", - "main": "./target_node", - "kibana": { - "devOnly": true - } + "main": "./target_node" } diff --git a/packages/kbn-timelion-grammar/kibana.jsonc b/packages/kbn-timelion-grammar/kibana.jsonc new file mode 100644 index 00000000000000..211d8483089c27 --- /dev/null +++ b/packages/kbn-timelion-grammar/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/timelion-grammar", + "owner": "@elastic/kibana-vis-editors", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-tinymath/kibana.jsonc b/packages/kbn-tinymath/kibana.jsonc new file mode 100644 index 00000000000000..6ebf2ac0c00ea6 --- /dev/null +++ b/packages/kbn-tinymath/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/tinymath", + "owner": "@elastic/kibana-vis-editors", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-tooling-log/kibana.jsonc b/packages/kbn-tooling-log/kibana.jsonc new file mode 100644 index 00000000000000..88eecfa75bf388 --- /dev/null +++ b/packages/kbn-tooling-log/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/tooling-log", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-tooling-log/package.json b/packages/kbn-tooling-log/package.json index 53137ddf6366ef..5af0ae2aca79ab 100644 --- a/packages/kbn-tooling-log/package.json +++ b/packages/kbn-tooling-log/package.json @@ -3,8 +3,5 @@ "private": true, "version": "1.0.0", "main": "./target_node/index.js", - "license": "SSPL-1.0 OR Elastic License 2.0", - "kibana": { - "devOnly": true - } + "license": "SSPL-1.0 OR Elastic License 2.0" } diff --git a/packages/kbn-type-summarizer-cli/kibana.jsonc b/packages/kbn-type-summarizer-cli/kibana.jsonc new file mode 100644 index 00000000000000..88434bc04812d8 --- /dev/null +++ b/packages/kbn-type-summarizer-cli/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/type-summarizer-cli", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-type-summarizer-cli/package.json b/packages/kbn-type-summarizer-cli/package.json index fafc57c3c7d08d..8b71981054f113 100644 --- a/packages/kbn-type-summarizer-cli/package.json +++ b/packages/kbn-type-summarizer-cli/package.json @@ -3,8 +3,5 @@ "private": true, "version": "1.0.0", "main": "./target_node/index.js", - "license": "SSPL-1.0 OR Elastic License 2.0", - "kibana": { - "devOnly": true - } + "license": "SSPL-1.0 OR Elastic License 2.0" } diff --git a/packages/kbn-type-summarizer-core/kibana.jsonc b/packages/kbn-type-summarizer-core/kibana.jsonc new file mode 100644 index 00000000000000..322a6c152b2f79 --- /dev/null +++ b/packages/kbn-type-summarizer-core/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/type-summarizer-core", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-type-summarizer-core/package.json b/packages/kbn-type-summarizer-core/package.json index a1dfb4fea87517..1ad7560b3571ce 100644 --- a/packages/kbn-type-summarizer-core/package.json +++ b/packages/kbn-type-summarizer-core/package.json @@ -3,8 +3,5 @@ "private": true, "version": "1.0.0", "main": "./target_node/index.js", - "license": "SSPL-1.0 OR Elastic License 2.0", - "kibana": { - "devOnly": true - } + "license": "SSPL-1.0 OR Elastic License 2.0" } diff --git a/packages/kbn-type-summarizer/kibana.jsonc b/packages/kbn-type-summarizer/kibana.jsonc new file mode 100644 index 00000000000000..e4eb9dc7c60347 --- /dev/null +++ b/packages/kbn-type-summarizer/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/type-summarizer", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-type-summarizer/package.json b/packages/kbn-type-summarizer/package.json index b9118e2b43a3dc..9ea19f6497219d 100644 --- a/packages/kbn-type-summarizer/package.json +++ b/packages/kbn-type-summarizer/package.json @@ -3,8 +3,5 @@ "private": true, "version": "1.0.0", "main": "./target_node/index.js", - "license": "SSPL-1.0 OR Elastic License 2.0", - "kibana": { - "devOnly": true - } + "license": "SSPL-1.0 OR Elastic License 2.0" } diff --git a/packages/kbn-typed-react-router-config/kibana.jsonc b/packages/kbn-typed-react-router-config/kibana.jsonc new file mode 100644 index 00000000000000..51882f6266c34f --- /dev/null +++ b/packages/kbn-typed-react-router-config/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/typed-react-router-config", + "owner": "@elastic/apm-ui", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-ui-framework/kibana.jsonc b/packages/kbn-ui-framework/kibana.jsonc new file mode 100644 index 00000000000000..eaef655970e37f --- /dev/null +++ b/packages/kbn-ui-framework/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/ui-framework", + "owner": "@elastic/kibana-design", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-ui-shared-deps-npm/kibana.jsonc b/packages/kbn-ui-shared-deps-npm/kibana.jsonc new file mode 100644 index 00000000000000..b7d47a5ccff4bb --- /dev/null +++ b/packages/kbn-ui-shared-deps-npm/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/ui-shared-deps-npm", + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-ui-shared-deps-npm/src/public_path_loader.js b/packages/kbn-ui-shared-deps-npm/src/public_path_loader.js index 6b2c0a8e9512f1..4f52032b316acc 100644 --- a/packages/kbn-ui-shared-deps-npm/src/public_path_loader.js +++ b/packages/kbn-ui-shared-deps-npm/src/public_path_loader.js @@ -7,6 +7,7 @@ */ const Qs = require('querystring'); +// eslint-disable-next-line import/no-extraneous-dependencies const { stringifyRequest } = require('loader-utils'); const VAL_LOADER = require.resolve('val-loader'); diff --git a/packages/kbn-ui-shared-deps-src/kibana.jsonc b/packages/kbn-ui-shared-deps-src/kibana.jsonc new file mode 100644 index 00000000000000..49da1e45e9d278 --- /dev/null +++ b/packages/kbn-ui-shared-deps-src/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/ui-shared-deps-src", + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-ui-theme/kibana.jsonc b/packages/kbn-ui-theme/kibana.jsonc new file mode 100644 index 00000000000000..3f90299e803601 --- /dev/null +++ b/packages/kbn-ui-theme/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/ui-theme", + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-user-profile-components/kibana.jsonc b/packages/kbn-user-profile-components/kibana.jsonc new file mode 100644 index 00000000000000..d4c7f266fe60be --- /dev/null +++ b/packages/kbn-user-profile-components/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/user-profile-components", + "owner": "@elastic/kibana-security", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-utility-types-jest/kibana.jsonc b/packages/kbn-utility-types-jest/kibana.jsonc new file mode 100644 index 00000000000000..83eaa2ce42aa23 --- /dev/null +++ b/packages/kbn-utility-types-jest/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/utility-types-jest", + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-utility-types-jest/package.json b/packages/kbn-utility-types-jest/package.json index 808dd51dec7937..b409e49384fc77 100644 --- a/packages/kbn-utility-types-jest/package.json +++ b/packages/kbn-utility-types-jest/package.json @@ -3,8 +3,5 @@ "version": "1.0.0", "private": true, "license": "SSPL-1.0 OR Elastic License 2.0", - "main": "target_node/index.js", - "kibana": { - "devOnly": false - } + "main": "target_node/index.js" } \ No newline at end of file diff --git a/packages/kbn-utility-types/kibana.jsonc b/packages/kbn-utility-types/kibana.jsonc new file mode 100644 index 00000000000000..c041668a7689b8 --- /dev/null +++ b/packages/kbn-utility-types/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/utility-types", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-utility-types/package.json b/packages/kbn-utility-types/package.json index f79164388f18b0..fa899c332dee9a 100644 --- a/packages/kbn-utility-types/package.json +++ b/packages/kbn-utility-types/package.json @@ -4,9 +4,6 @@ "private": true, "license": "SSPL-1.0 OR Elastic License 2.0", "main": "target_node/index.js", - "kibana": { - "devOnly": false - }, "scripts": { "test": "../../node_modules/.bin/tsd src/tsd_tests" } diff --git a/packages/kbn-utils/kibana.jsonc b/packages/kbn-utils/kibana.jsonc new file mode 100644 index 00000000000000..1e6935937f6e5b --- /dev/null +++ b/packages/kbn-utils/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/utils", + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-yarn-lock-validator/kibana.jsonc b/packages/kbn-yarn-lock-validator/kibana.jsonc new file mode 100644 index 00000000000000..9ff3e33975597e --- /dev/null +++ b/packages/kbn-yarn-lock-validator/kibana.jsonc @@ -0,0 +1,8 @@ +{ + "type": "shared-common", + "id": "@kbn/yarn-lock-validator", + "devOnly": true, + "owner": "@elastic/kibana-operations", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/kbn-yarn-lock-validator/package.json b/packages/kbn-yarn-lock-validator/package.json index e7d0c00269ac7b..4d024fb6aded5e 100644 --- a/packages/kbn-yarn-lock-validator/package.json +++ b/packages/kbn-yarn-lock-validator/package.json @@ -3,8 +3,5 @@ "private": true, "version": "1.0.0", "main": "./target_node/index.js", - "license": "SSPL-1.0 OR Elastic License 2.0", - "kibana": { - "devOnly": true - } + "license": "SSPL-1.0 OR Elastic License 2.0" } diff --git a/packages/kbn-yarn-lock-validator/src/validate_yarn_lock.ts b/packages/kbn-yarn-lock-validator/src/validate_yarn_lock.ts index 923a0f11fcbf6b..668f2911556c9c 100644 --- a/packages/kbn-yarn-lock-validator/src/validate_yarn_lock.ts +++ b/packages/kbn-yarn-lock-validator/src/validate_yarn_lock.ts @@ -93,14 +93,15 @@ export async function validateDependencies(log: SomeDevLog, yarnLock: YarnLock) // look for packages that have the the `kibana.devOnly` flag in their package.json // and make sure they aren't included in the production dependencies of Kibana const bazelPackages = await discoverBazelPackages(REPO_ROOT); - const devOnlyPackagesInProduction = bazelPackages - .filter((p) => p.isDevOnly() && Object.hasOwn(kibanaPackageJson.dependencies, p.pkg.name)) - .map((p) => p.pkg.name); - + const devOnlyPackagesInProduction = bazelPackages.flatMap((p) => + p.isDevOnly() && Object.hasOwn(kibanaPackageJson.dependencies, p.manifest.id) + ? p.manifest.id + : [] + ); if (devOnlyPackagesInProduction.length) { log.error(dedent` Some of the packages in the production dependency chain for Kibana and X-Pack are - flagged with "kibana.devOnly" in their package.json. Please check changes made to + flagged with "devOnly" in their package.json. Please check changes made to packages and their dependencies to ensure they don't end up in production. The devOnly dependencies that are being dependend on in production are: diff --git a/packages/shared-ux/avatar/solution/kibana.jsonc b/packages/shared-ux/avatar/solution/kibana.jsonc new file mode 100644 index 00000000000000..6a2ea7f7563818 --- /dev/null +++ b/packages/shared-ux/avatar/solution/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/shared-ux-avatar-solution", + "owner": "@elastic/shared-ux", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/shared-ux/button/exit_full_screen/impl/kibana.jsonc b/packages/shared-ux/button/exit_full_screen/impl/kibana.jsonc new file mode 100644 index 00000000000000..328b3ebbdc7bbd --- /dev/null +++ b/packages/shared-ux/button/exit_full_screen/impl/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/shared-ux-button-exit-full-screen", + "owner": "@elastic/shared-ux", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/shared-ux/button/exit_full_screen/mocks/kibana.jsonc b/packages/shared-ux/button/exit_full_screen/mocks/kibana.jsonc new file mode 100644 index 00000000000000..4cfb6b20a297b6 --- /dev/null +++ b/packages/shared-ux/button/exit_full_screen/mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/shared-ux-button-exit-full-screen-mocks", + "owner": "@elastic/shared-ux", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/shared-ux/button/exit_full_screen/types/kibana.jsonc b/packages/shared-ux/button/exit_full_screen/types/kibana.jsonc new file mode 100644 index 00000000000000..00597791c1c83e --- /dev/null +++ b/packages/shared-ux/button/exit_full_screen/types/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/shared-ux-button-exit-full-screen-types", + "owner": "@elastic/shared-ux", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/shared-ux/button_toolbar/kibana.jsonc b/packages/shared-ux/button_toolbar/kibana.jsonc new file mode 100644 index 00000000000000..45d7bb2c935a93 --- /dev/null +++ b/packages/shared-ux/button_toolbar/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/shared-ux-button-toolbar", + "owner": "@elastic/shared-ux", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/shared-ux/card/no_data/impl/kibana.jsonc b/packages/shared-ux/card/no_data/impl/kibana.jsonc new file mode 100644 index 00000000000000..38ce883168de3a --- /dev/null +++ b/packages/shared-ux/card/no_data/impl/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/shared-ux-card-no-data", + "owner": "@elastic/shared-ux", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/shared-ux/card/no_data/mocks/kibana.jsonc b/packages/shared-ux/card/no_data/mocks/kibana.jsonc new file mode 100644 index 00000000000000..79230acd9e35c3 --- /dev/null +++ b/packages/shared-ux/card/no_data/mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/shared-ux-card-no-data-mocks", + "owner": "@elastic/shared-ux", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/shared-ux/card/no_data/types/kibana.jsonc b/packages/shared-ux/card/no_data/types/kibana.jsonc new file mode 100644 index 00000000000000..d612fb80bfcd57 --- /dev/null +++ b/packages/shared-ux/card/no_data/types/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/shared-ux-card-no-data-types", + "owner": "@elastic/shared-ux", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/shared-ux/link/redirect_app/impl/kibana.jsonc b/packages/shared-ux/link/redirect_app/impl/kibana.jsonc new file mode 100644 index 00000000000000..38f34416473b91 --- /dev/null +++ b/packages/shared-ux/link/redirect_app/impl/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/shared-ux-link-redirect-app", + "owner": "@elastic/shared-ux", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/shared-ux/link/redirect_app/mocks/kibana.jsonc b/packages/shared-ux/link/redirect_app/mocks/kibana.jsonc new file mode 100644 index 00000000000000..f9991820df0226 --- /dev/null +++ b/packages/shared-ux/link/redirect_app/mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/shared-ux-link-redirect-app-mocks", + "owner": "@elastic/shared-ux", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/shared-ux/link/redirect_app/types/kibana.jsonc b/packages/shared-ux/link/redirect_app/types/kibana.jsonc new file mode 100644 index 00000000000000..4de2b13ec358f2 --- /dev/null +++ b/packages/shared-ux/link/redirect_app/types/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/shared-ux-link-redirect-app-types", + "owner": "@elastic/shared-ux", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/shared-ux/page/analytics_no_data/impl/kibana.jsonc b/packages/shared-ux/page/analytics_no_data/impl/kibana.jsonc new file mode 100644 index 00000000000000..6b44af223ee87e --- /dev/null +++ b/packages/shared-ux/page/analytics_no_data/impl/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/shared-ux-page-analytics-no-data", + "owner": "@elastic/shared-ux", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/shared-ux/page/analytics_no_data/mocks/kibana.jsonc b/packages/shared-ux/page/analytics_no_data/mocks/kibana.jsonc new file mode 100644 index 00000000000000..30284a98f4b102 --- /dev/null +++ b/packages/shared-ux/page/analytics_no_data/mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/shared-ux-page-analytics-no-data-mocks", + "owner": "@elastic/shared-ux", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/shared-ux/page/analytics_no_data/types/kibana.jsonc b/packages/shared-ux/page/analytics_no_data/types/kibana.jsonc new file mode 100644 index 00000000000000..c5f393e68b31db --- /dev/null +++ b/packages/shared-ux/page/analytics_no_data/types/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/shared-ux-page-analytics-no-data-types", + "owner": "@elastic/shared-ux", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/shared-ux/page/kibana_no_data/impl/kibana.jsonc b/packages/shared-ux/page/kibana_no_data/impl/kibana.jsonc new file mode 100644 index 00000000000000..afbc38e5c31ea7 --- /dev/null +++ b/packages/shared-ux/page/kibana_no_data/impl/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/shared-ux-page-kibana-no-data", + "owner": "@elastic/shared-ux", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/shared-ux/page/kibana_no_data/mocks/kibana.jsonc b/packages/shared-ux/page/kibana_no_data/mocks/kibana.jsonc new file mode 100644 index 00000000000000..40b9b7ae6949fe --- /dev/null +++ b/packages/shared-ux/page/kibana_no_data/mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/shared-ux-page-kibana-no-data-mocks", + "owner": "@elastic/shared-ux", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/shared-ux/page/kibana_no_data/types/kibana.jsonc b/packages/shared-ux/page/kibana_no_data/types/kibana.jsonc new file mode 100644 index 00000000000000..b29d44238995fc --- /dev/null +++ b/packages/shared-ux/page/kibana_no_data/types/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/shared-ux-page-kibana-no-data-types", + "owner": "@elastic/shared-ux", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/shared-ux/page/kibana_template/impl/kibana.jsonc b/packages/shared-ux/page/kibana_template/impl/kibana.jsonc new file mode 100644 index 00000000000000..6d1d8ff74de775 --- /dev/null +++ b/packages/shared-ux/page/kibana_template/impl/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/shared-ux-page-kibana-template", + "owner": "@elastic/shared-ux", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/shared-ux/page/kibana_template/mocks/kibana.jsonc b/packages/shared-ux/page/kibana_template/mocks/kibana.jsonc new file mode 100644 index 00000000000000..43a17e3257739c --- /dev/null +++ b/packages/shared-ux/page/kibana_template/mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/shared-ux-page-kibana-template-mocks", + "owner": "@elastic/shared-ux", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/shared-ux/page/kibana_template/types/kibana.jsonc b/packages/shared-ux/page/kibana_template/types/kibana.jsonc new file mode 100644 index 00000000000000..b4b18d25baf0be --- /dev/null +++ b/packages/shared-ux/page/kibana_template/types/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/shared-ux-page-kibana-template-types", + "owner": "@elastic/shared-ux", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/shared-ux/page/no_data/impl/kibana.jsonc b/packages/shared-ux/page/no_data/impl/kibana.jsonc new file mode 100644 index 00000000000000..2a0576ad190bdc --- /dev/null +++ b/packages/shared-ux/page/no_data/impl/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/shared-ux-page-no-data", + "owner": "@elastic/shared-ux", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/shared-ux/page/no_data/mocks/kibana.jsonc b/packages/shared-ux/page/no_data/mocks/kibana.jsonc new file mode 100644 index 00000000000000..6735d457c937d3 --- /dev/null +++ b/packages/shared-ux/page/no_data/mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/shared-ux-page-no-data-mocks", + "owner": "@elastic/shared-ux", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/shared-ux/page/no_data/types/kibana.jsonc b/packages/shared-ux/page/no_data/types/kibana.jsonc new file mode 100644 index 00000000000000..02a6dbc2f8fa1d --- /dev/null +++ b/packages/shared-ux/page/no_data/types/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/shared-ux-page-no-data-types", + "owner": "@elastic/shared-ux", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/shared-ux/page/no_data_config/impl/kibana.jsonc b/packages/shared-ux/page/no_data_config/impl/kibana.jsonc new file mode 100644 index 00000000000000..991cb4ef781b9d --- /dev/null +++ b/packages/shared-ux/page/no_data_config/impl/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/shared-ux-page-no-data-config", + "owner": "@elastic/shared-ux", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/shared-ux/page/no_data_config/mocks/kibana.jsonc b/packages/shared-ux/page/no_data_config/mocks/kibana.jsonc new file mode 100644 index 00000000000000..d87174032f5539 --- /dev/null +++ b/packages/shared-ux/page/no_data_config/mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/shared-ux-page-no-data-config-mocks", + "owner": "@elastic/shared-ux", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/shared-ux/page/no_data_config/types/kibana.jsonc b/packages/shared-ux/page/no_data_config/types/kibana.jsonc new file mode 100644 index 00000000000000..2491f5442db8c5 --- /dev/null +++ b/packages/shared-ux/page/no_data_config/types/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/shared-ux-page-no-data-config-types", + "owner": "@elastic/shared-ux", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/shared-ux/page/solution_nav/kibana.jsonc b/packages/shared-ux/page/solution_nav/kibana.jsonc new file mode 100644 index 00000000000000..8c62fb2f3e7502 --- /dev/null +++ b/packages/shared-ux/page/solution_nav/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/shared-ux-page-solution-nav", + "owner": "@elastic/shared-ux", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/shared-ux/prompt/no_data_views/impl/kibana.jsonc b/packages/shared-ux/prompt/no_data_views/impl/kibana.jsonc new file mode 100644 index 00000000000000..4861e3d3b6eddd --- /dev/null +++ b/packages/shared-ux/prompt/no_data_views/impl/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/shared-ux-prompt-no-data-views", + "owner": "@elastic/shared-ux", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/shared-ux/prompt/no_data_views/mocks/kibana.jsonc b/packages/shared-ux/prompt/no_data_views/mocks/kibana.jsonc new file mode 100644 index 00000000000000..65532173dd0ede --- /dev/null +++ b/packages/shared-ux/prompt/no_data_views/mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/shared-ux-prompt-no-data-views-mocks", + "owner": "@elastic/shared-ux", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/shared-ux/prompt/no_data_views/types/kibana.jsonc b/packages/shared-ux/prompt/no_data_views/types/kibana.jsonc new file mode 100644 index 00000000000000..1385b91ec370e6 --- /dev/null +++ b/packages/shared-ux/prompt/no_data_views/types/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/shared-ux-prompt-no-data-views-types", + "owner": "@elastic/shared-ux", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/shared-ux/storybook/config/kibana.jsonc b/packages/shared-ux/storybook/config/kibana.jsonc new file mode 100644 index 00000000000000..9a3b26cb20f831 --- /dev/null +++ b/packages/shared-ux/storybook/config/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/shared-ux-storybook-config", + "owner": "@elastic/shared-ux", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/shared-ux/storybook/mock/kibana.jsonc b/packages/shared-ux/storybook/mock/kibana.jsonc new file mode 100644 index 00000000000000..305626d6f3cdce --- /dev/null +++ b/packages/shared-ux/storybook/mock/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/shared-ux-storybook-mock", + "owner": "@elastic/shared-ux", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/src/core/public/core_app/status/components/status_table.test.tsx b/src/core/public/core_app/status/components/status_table.test.tsx index 1aa39325d808e5..d4bfccd7d0b2a2 100644 --- a/src/core/public/core_app/status/components/status_table.test.tsx +++ b/src/core/public/core_app/status/components/status_table.test.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { shallow } from 'enzyme'; -import { ServiceStatus } from '../../../../types/status'; +import type { StatusInfoServiceStatus as ServiceStatus } from '@kbn/core-status-common-internal'; import { StatusTable } from './status_table'; const state = { diff --git a/src/core/public/core_app/status/components/version_header.test.tsx b/src/core/public/core_app/status/components/version_header.test.tsx index 172a720a517511..bfe2d6a2c40ded 100644 --- a/src/core/public/core_app/status/components/version_header.test.tsx +++ b/src/core/public/core_app/status/components/version_header.test.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { mountWithIntl, findTestSubject } from '@kbn/test-jest-helpers'; -import type { ServerVersion } from '../../../../types/status'; +import type { ServerVersion } from '@kbn/core-status-common-internal'; import { VersionHeader } from './version_header'; const buildServerVersion = (parts: Partial = {}): ServerVersion => ({ diff --git a/src/core/public/core_app/status/components/version_header.tsx b/src/core/public/core_app/status/components/version_header.tsx index c9b4109cf1f78b..81b76f771cda14 100644 --- a/src/core/public/core_app/status/components/version_header.tsx +++ b/src/core/public/core_app/status/components/version_header.tsx @@ -14,7 +14,7 @@ import { EuiText, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; -import type { ServerVersion } from '../../../../types/status'; +import type { ServerVersion } from '@kbn/core-status-common-internal'; interface VersionHeaderProps { version: ServerVersion; diff --git a/src/core/public/core_app/status/lib/load_status.test.ts b/src/core/public/core_app/status/lib/load_status.test.ts index f14e250fec4b50..ac40eedfccb7d7 100644 --- a/src/core/public/core_app/status/lib/load_status.test.ts +++ b/src/core/public/core_app/status/lib/load_status.test.ts @@ -7,7 +7,7 @@ */ import { httpServiceMock } from '@kbn/core-http-browser-mocks'; -import type { StatusResponse } from '../../../../types/status'; +import type { StatusResponse } from '@kbn/core-status-common-internal'; import { notificationServiceMock } from '@kbn/core-notifications-browser-mocks'; import { mocked } from '@kbn/core-metrics-collectors-server-mocks'; import { loadStatus } from './load_status'; diff --git a/src/core/public/core_app/status/lib/load_status.ts b/src/core/public/core_app/status/lib/load_status.ts index 6a5dfa7ad3e45c..5a4b2b5907ea2c 100644 --- a/src/core/public/core_app/status/lib/load_status.ts +++ b/src/core/public/core_app/status/lib/load_status.ts @@ -9,7 +9,11 @@ import { i18n } from '@kbn/i18n'; import type { HttpSetup } from '@kbn/core-http-browser'; import type { NotificationsSetup } from '@kbn/core-notifications-browser'; -import type { StatusResponse, ServiceStatus, ServiceStatusLevel } from '../../../../types/status'; +import type { ServiceStatusLevelId } from '@kbn/core-status-common'; +import type { + StatusResponse, + StatusInfoServiceStatus as ServiceStatus, +} from '@kbn/core-status-common-internal'; import type { DataType } from '.'; interface MetricMeta { @@ -18,6 +22,7 @@ interface MetricMeta { value?: number[]; type?: DataType; } + export interface Metric { name: string; value: number | number[]; @@ -32,7 +37,7 @@ export interface FormattedStatus { } export interface StatusState { - id: ServiceStatusLevel; + id: ServiceStatusLevelId; title: string; message: string; uiColor: string; @@ -144,7 +149,7 @@ function formatStatus(id: string, status: ServiceStatus): FormattedStatus { }; } -export const STATUS_LEVEL_UI_ATTRS: Record = { +export const STATUS_LEVEL_UI_ATTRS: Record = { critical: { title: i18n.translate('core.status.redTitle', { defaultMessage: 'Red', diff --git a/src/core/public/core_app/status/lib/status_level.test.ts b/src/core/public/core_app/status/lib/status_level.test.ts index 44322748992a0c..d58144a91d939d 100644 --- a/src/core/public/core_app/status/lib/status_level.test.ts +++ b/src/core/public/core_app/status/lib/status_level.test.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { ServiceStatus } from '../../../../types/status'; +import type { StatusInfoServiceStatus as ServiceStatus } from '@kbn/core-status-common-internal'; import { getLevelSortValue, groupByLevel, getHighestStatus } from './status_level'; import { FormattedStatus, StatusState } from './load_status'; diff --git a/src/core/public/core_app/status/lib/status_level.ts b/src/core/public/core_app/status/lib/status_level.ts index f0c3be949057f4..d6b3033cfcc91c 100644 --- a/src/core/public/core_app/status/lib/status_level.ts +++ b/src/core/public/core_app/status/lib/status_level.ts @@ -6,10 +6,10 @@ * Side Public License, v 1. */ -import type { ServiceStatusLevel } from '../../../../types/status'; +import type { ServiceStatusLevelId } from '@kbn/core-status-common'; import { FormattedStatus, StatusState, STATUS_LEVEL_UI_ATTRS } from './load_status'; -export const orderedLevels: ServiceStatusLevel[] = [ +export const orderedLevels: ServiceStatusLevelId[] = [ 'critical', 'unavailable', 'degraded', @@ -21,7 +21,7 @@ export const groupByLevel = (statuses: FormattedStatus[]) => { const existing = map.get(status.state.id) ?? []; map.set(status.state.id, [...existing, status]); return map; - }, new Map()); + }, new Map()); }; export const getHighestStatus = (statuses: FormattedStatus[]): Omit => { diff --git a/src/core/server/index.ts b/src/core/server/index.ts index 6c539dd1f20f64..3aa3cbd52c4e4c 100644 --- a/src/core/server/index.ts +++ b/src/core/server/index.ts @@ -66,12 +66,12 @@ import type { } from '@kbn/core-saved-objects-server'; import type { DeprecationsServiceSetup } from '@kbn/core-deprecations-server'; import type { CoreUsageDataStart, CoreUsageDataSetup } from '@kbn/core-usage-data-server'; +import type { I18nServiceSetup } from '@kbn/core-i18n-server'; +import type { StatusServiceSetup } from '@kbn/core-status-server'; -import { I18nServiceSetup } from '@kbn/core-i18n-server'; import { HttpResources } from './http_resources'; import { PluginsServiceSetup, PluginsServiceStart, PluginOpaqueId } from './plugins'; import { UiSettingsServiceSetup, UiSettingsServiceStart } from './ui_settings'; -import { StatusServiceSetup } from './status'; import type { CoreRequestHandlerContext } from './core_route_handler_context'; import type { PrebootCoreRequestHandlerContext } from './preboot_core_route_handler_context'; @@ -433,8 +433,9 @@ export type { DeprecationsDetails } from '@kbn/core-deprecations-common'; export type { AppCategory } from '@kbn/core-application-common'; export { DEFAULT_APP_CATEGORIES, APP_WRAPPER_CLASS } from '@kbn/core-application-common'; -export { ServiceStatusLevels } from './status'; -export type { CoreStatus, ServiceStatus, ServiceStatusLevel, StatusServiceSetup } from './status'; +export { ServiceStatusLevels } from '@kbn/core-status-common'; +export type { CoreStatus, ServiceStatus, ServiceStatusLevel } from '@kbn/core-status-common'; +export type { StatusServiceSetup } from '@kbn/core-status-server'; export type { DocLinksServiceStart, DocLinksServiceSetup } from '@kbn/core-doc-links-server'; diff --git a/src/core/server/integration_tests/status/routes/status.test.ts b/src/core/server/integration_tests/status/routes/status.test.ts index 980bae6cfd2bb8..27e18979e3df08 100644 --- a/src/core/server/integration_tests/status/routes/status.test.ts +++ b/src/core/server/integration_tests/status/routes/status.test.ts @@ -15,13 +15,13 @@ import { createCoreContext, createHttpServer } from '@kbn/core-http-server-mocks import type { HttpService, InternalHttpServiceSetup } from '@kbn/core-http-server-internal'; import { metricsServiceMock } from '@kbn/core-metrics-server-mocks'; import type { MetricsServiceSetup } from '@kbn/core-metrics-server'; - -import { registerStatusRoute } from '../../../status/routes/status'; -import { ServiceStatus, ServiceStatusLevels, ServiceStatusLevel } from '../../../status/types'; -import { statusServiceMock } from '../../../status/status_service.mock'; +import { ServiceStatus, ServiceStatusLevels, ServiceStatusLevel } from '@kbn/core-status-common'; +import { statusServiceMock } from '@kbn/core-status-server-mocks'; import { executionContextServiceMock } from '@kbn/core-execution-context-server-mocks'; import { contextServiceMock } from '@kbn/core-http-context-server-mocks'; +import { registerStatusRoute } from '@kbn/core-status-server-internal'; + const coreId = Symbol('core'); const createServiceStatus = ( diff --git a/src/core/server/internal_types.ts b/src/core/server/internal_types.ts index 4f655a9e0f3c85..4a74d2e0aadcb6 100644 --- a/src/core/server/internal_types.ts +++ b/src/core/server/internal_types.ts @@ -52,6 +52,7 @@ import { import type { CoreUsageDataStart } from '@kbn/core-usage-data-server'; import type { InternalCoreUsageDataSetup } from '@kbn/core-usage-data-base-server-internal'; import type { I18nServiceSetup } from '@kbn/core-i18n-server'; +import type { InternalStatusServiceSetup } from '@kbn/core-status-server-internal'; import { InternalUiSettingsServicePreboot, InternalUiSettingsServiceSetup, @@ -59,7 +60,6 @@ import { } from './ui_settings'; import { InternalRenderingServiceSetup } from './rendering'; import { InternalHttpResourcesPreboot, InternalHttpResourcesSetup } from './http_resources'; -import { InternalStatusServiceSetup } from './status'; /** @internal */ export interface InternalCorePreboot { diff --git a/src/core/server/mocks.ts b/src/core/server/mocks.ts index 5efbbdfbad39be..66ff3aea68b379 100644 --- a/src/core/server/mocks.ts +++ b/src/core/server/mocks.ts @@ -29,6 +29,7 @@ import { savedObjectsClientMock } from '@kbn/core-saved-objects-api-server-mocks import { deprecationsServiceMock } from '@kbn/core-deprecations-server-mocks'; import { coreUsageDataServiceMock } from '@kbn/core-usage-data-server-mocks'; import { i18nServiceMock } from '@kbn/core-i18n-server-mocks'; +import { statusServiceMock } from '@kbn/core-status-server-mocks'; import type { PluginInitializerContext, CoreSetup, @@ -41,7 +42,6 @@ import { httpResourcesMock } from './http_resources/http_resources_service.mock' import { renderingMock } from './rendering/rendering_service.mock'; import { uiSettingsServiceMock } from './ui_settings/ui_settings_service.mock'; import { SharedGlobalConfig } from './plugins'; -import { statusServiceMock } from './status/status_service.mock'; export { configServiceMock, configDeprecationsMock } from '@kbn/config-mocks'; export { loggingSystemMock } from '@kbn/core-logging-server-mocks'; @@ -58,7 +58,7 @@ export { migrationMocks } from '@kbn/core-saved-objects-migration-server-mocks'; export { uiSettingsServiceMock } from './ui_settings/ui_settings_service.mock'; export { metricsServiceMock } from '@kbn/core-metrics-server-mocks'; export { renderingMock } from './rendering/rendering_service.mock'; -export { statusServiceMock } from './status/status_service.mock'; +export { statusServiceMock } from '@kbn/core-status-server-mocks'; export { contextServiceMock } from '@kbn/core-http-context-server-mocks'; export { capabilitiesServiceMock } from '@kbn/core-capabilities-server-mocks'; export { deprecationsServiceMock } from '@kbn/core-deprecations-server-mocks'; diff --git a/src/core/server/rendering/__mocks__/params.ts b/src/core/server/rendering/__mocks__/params.ts index 71b4996590c645..c75353b87a65db 100644 --- a/src/core/server/rendering/__mocks__/params.ts +++ b/src/core/server/rendering/__mocks__/params.ts @@ -9,8 +9,8 @@ import { mockCoreContext } from '@kbn/core-base-server-mocks'; import { httpServiceMock } from '@kbn/core-http-server-mocks'; import { elasticsearchServiceMock } from '@kbn/core-elasticsearch-server-mocks'; +import { statusServiceMock } from '@kbn/core-status-server-mocks'; import { pluginServiceMock } from '../../plugins/plugins_service.mock'; -import { statusServiceMock } from '../../status/status_service.mock'; const context = mockCoreContext.create(); const httpPreboot = httpServiceMock.createInternalPrebootContract(); diff --git a/src/core/server/rendering/types.ts b/src/core/server/rendering/types.ts index 0c5382627e9b66..60059637beb58b 100644 --- a/src/core/server/rendering/types.ts +++ b/src/core/server/rendering/types.ts @@ -15,9 +15,9 @@ import type { InternalHttpServiceSetup, } from '@kbn/core-http-server-internal'; import type { InternalElasticsearchServiceSetup } from '@kbn/core-elasticsearch-server-internal'; +import type { InternalStatusServiceSetup } from '@kbn/core-status-server-internal'; import { UiPlugins } from '../plugins'; import { IUiSettingsClient } from '../ui_settings'; -import type { InternalStatusServiceSetup } from '../status'; /** @internal */ export interface RenderingMetadata { diff --git a/src/core/server/server.test.mocks.ts b/src/core/server/server.test.mocks.ts index a6cce9aafde233..0b055ea5a8cf50 100644 --- a/src/core/server/server.test.mocks.ts +++ b/src/core/server/server.test.mocks.ts @@ -89,10 +89,10 @@ jest.doMock('@kbn/core-metrics-server-internal', () => ({ MetricsService: jest.fn(() => mockMetricsService), })); -import { statusServiceMock } from './status/status_service.mock'; +import { statusServiceMock } from '@kbn/core-status-server-mocks'; export const mockStatusService = statusServiceMock.create(); -jest.doMock('./status/status_service', () => ({ +jest.doMock('@kbn/core-status-server-internal', () => ({ StatusService: jest.fn(() => mockStatusService), })); diff --git a/src/core/server/server.ts b/src/core/server/server.ts index a6619f33e84f01..751da1845224d2 100644 --- a/src/core/server/server.ts +++ b/src/core/server/server.ts @@ -56,16 +56,14 @@ import { config as deprecationConfig, } from '@kbn/core-deprecations-server-internal'; import { CoreUsageDataService } from '@kbn/core-usage-data-server-internal'; +import { StatusService, statusConfig } from '@kbn/core-status-server-internal'; import { CoreApp } from './core_app'; import { HttpResourcesService } from './http_resources'; import { RenderingService } from './rendering'; import { UiSettingsService } from './ui_settings'; import { PluginsService, config as pluginsConfig } from './plugins'; -// do not try to shorten the import to `./status`, it will break server test mocking -import { StatusService } from './status/status_service'; import { config as uiSettingsConfig } from './ui_settings'; -import { config as statusConfig } from './status'; import { InternalCorePreboot, InternalCoreSetup, InternalCoreStart } from './internal_types'; import { CoreRouteHandlerContext } from './core_route_handler_context'; import { PrebootCoreRouteHandlerContext } from './preboot_core_route_handler_context'; diff --git a/src/core/server/test_utils.ts b/src/core/server/test_utils.ts index c96e168e162918..95a05aca5957bf 100644 --- a/src/core/server/test_utils.ts +++ b/src/core/server/test_utils.ts @@ -7,7 +7,6 @@ */ export { createHttpServer } from '@kbn/core-http-server-mocks'; -export { ServiceStatusLevelSnapshotSerializer } from './status/test_utils'; export { setupServer } from './integration_tests/saved_objects/routes/test_utils'; export { getDeprecationsFor, diff --git a/src/dev/build/tasks/build_packages_task.ts b/src/dev/build/tasks/build_packages_task.ts index 521b1299f423d0..fdb32731fdd8ed 100644 --- a/src/dev/build/tasks/build_packages_task.ts +++ b/src/dev/build/tasks/build_packages_task.ts @@ -23,7 +23,7 @@ export const BuildBazelPackages: Task = { await runBazel(['build', '//packages:build']); for (const pkg of packages) { - log.info(`Copying build of`, pkg.pkg.name, 'into build'); + log.info(`Copying build of`, pkg.manifest.id, 'into build'); const pkgDirInBuild = build.resolvePath(pkg.normalizedRepoRelativeDir); @@ -36,7 +36,23 @@ export const BuildBazelPackages: Task = { permissions: (rec) => (rec.isDirectory ? 0o755 : 0o644), }); - await write(Path.resolve(pkgDirInBuild, 'package.json'), JSON.stringify(pkg.pkg, null, 2)); + await write( + Path.resolve(pkgDirInBuild, 'kibana.jsonc'), + JSON.stringify(pkg.manifest, null, 2) + ); + await write( + Path.resolve(pkgDirInBuild, 'package.json'), + JSON.stringify( + { + ...pkg.pkg, + name: pkg.manifest.id, + version: config.getBuildVersion(), + private: undefined, + }, + null, + 2 + ) + ); } }, }; diff --git a/src/dev/build/tasks/clean_tasks.ts b/src/dev/build/tasks/clean_tasks.ts index 409f6a77b50bfc..bc4e5bca05675a 100644 --- a/src/dev/build/tasks/clean_tasks.ts +++ b/src/dev/build/tasks/clean_tasks.ts @@ -260,9 +260,15 @@ export const DeleteBazelPackagesFromBuildRoot: Task = { 'Deleting bazel packages outputs from build folder root as they are now installed as node_modules', async run(config, log, build) { - const bazelPackagesOnBuildRoot = (await discoverBazelPackages(REPO_ROOT)).map((pkg) => - build.resolvePath(pkg.normalizedRepoRelativeDir) - ); + const bazelPackagesOnBuildRoot = (await discoverBazelPackages(REPO_ROOT)).flatMap((pkg) => { + const bldSrc = build.resolvePath(pkg.normalizedRepoRelativeDir); + + if (pkg.manifest.type.startsWith('plugin-')) { + return bldSrc; + } + + return [bldSrc, build.resolvePath('node_modules', pkg.manifest.id, 'kibana.jsonc')]; + }); await deleteAll(bazelPackagesOnBuildRoot, log); }, diff --git a/src/dev/code_coverage/ingest_coverage/__tests__/enumerate_patterns.test.js b/src/dev/code_coverage/ingest_coverage/__tests__/enumerate_patterns.test.js index 6d5962f7f51e82..14f7cefc78cae9 100644 --- a/src/dev/code_coverage/ingest_coverage/__tests__/enumerate_patterns.test.js +++ b/src/dev/code_coverage/ingest_coverage/__tests__/enumerate_patterns.test.js @@ -34,11 +34,4 @@ describe(`enumeratePatterns`, () => { 'src/plugins/charts/common/static/color_maps/color_maps.ts kibana-app' ); }); - it(`should resolve x-pack/plugins/security_solution/public/common/components/exceptions/edit_exception_flyout/translations.ts to kibana-security`, () => { - const short = - 'x-pack/plugins/security_solution/public/common/components/exceptions/edit_exception_flyout'; - const actual = enumeratePatterns(REPO_ROOT)(log)(new Map([[short, ['kibana-security']]])); - - expect(actual.flat()).toContain(`${short}/translations.ts kibana-security`); - }); }); diff --git a/src/plugins/chart_expressions/expression_metric/public/components/metric_vis.tsx b/src/plugins/chart_expressions/expression_metric/public/components/metric_vis.tsx index 05a0266e676d05..539b41950a23cb 100644 --- a/src/plugins/chart_expressions/expression_metric/public/components/metric_vis.tsx +++ b/src/plugins/chart_expressions/expression_metric/public/components/metric_vis.tsx @@ -321,12 +321,6 @@ export const MetricVis = ({ ); }, [grid.length, scrollDimensions.height]); - // force chart to re-render to circumvent a charts bug - const magicKey = useRef(0); - useEffect(() => { - magicKey.current++; - }, [data]); - return (
- + { + return { + name: 'event_annotations_result', + aliases: [], + type: 'event_annotations_result', + inputTypes: ['null'], + help: strings.getAnnotationLayerFnHelp(), + args: { + layers: { + types: [EXTENDED_ANNOTATION_LAYER], + multi: true, + help: strings.getAnnotationLayerFnHelp(), + }, + datatable: { + types: ['datatable'], + help: strings.getAnnotationLayerFnHelp(), + }, + }, + fn: (input, args) => { + return { + ...args, + type: 'event_annotations_result', + layers: args.layers || [], + datatable: args.datatable || {}, + }; + }, + }; +} diff --git a/src/plugins/chart_expressions/expression_xy/common/expression_functions/extended_annotation_layer.ts b/src/plugins/chart_expressions/expression_xy/common/expression_functions/extended_annotation_layer.ts index 7c361000f7823f..5098be2aa2705f 100644 --- a/src/plugins/chart_expressions/expression_xy/common/expression_functions/extended_annotation_layer.ts +++ b/src/plugins/chart_expressions/expression_xy/common/expression_functions/extended_annotation_layer.ts @@ -6,14 +6,14 @@ * Side Public License, v 1. */ -import type { Datatable, ExpressionFunctionDefinition } from '@kbn/expressions-plugin/common'; +import type { ExpressionFunctionDefinition } from '@kbn/expressions-plugin/common'; import { LayerTypes, EXTENDED_ANNOTATION_LAYER } from '../constants'; import { ExtendedAnnotationLayerConfigResult, ExtendedAnnotationLayerArgs } from '../types'; import { strings } from '../i18n'; export function extendedAnnotationLayerFunction(): ExpressionFunctionDefinition< typeof EXTENDED_ANNOTATION_LAYER, - Datatable, + null, ExtendedAnnotationLayerArgs, ExtendedAnnotationLayerConfigResult > { @@ -21,7 +21,7 @@ export function extendedAnnotationLayerFunction(): ExpressionFunctionDefinition< name: EXTENDED_ANNOTATION_LAYER, aliases: [], type: EXTENDED_ANNOTATION_LAYER, - inputTypes: ['datatable'], + inputTypes: ['null'], help: strings.getAnnotationLayerFnHelp(), args: { simpleView: { diff --git a/src/plugins/chart_expressions/expression_xy/common/expression_functions/layered_xy_vis.ts b/src/plugins/chart_expressions/expression_xy/common/expression_functions/layered_xy_vis.ts index 392c9a0d5830ac..0ca9a3ac4e5cce 100644 --- a/src/plugins/chart_expressions/expression_xy/common/expression_functions/layered_xy_vis.ts +++ b/src/plugins/chart_expressions/expression_xy/common/expression_functions/layered_xy_vis.ts @@ -12,7 +12,6 @@ import { EXTENDED_DATA_LAYER, REFERENCE_LINE_LAYER, LAYERED_XY_VIS, - EXTENDED_ANNOTATION_LAYER, REFERENCE_LINE, } from '../constants'; import { commonXYArgs } from './common_xy_args'; @@ -26,12 +25,18 @@ export const layeredXyVisFunction: LayeredXyVisFn = { args: { ...commonXYArgs, layers: { - types: [EXTENDED_DATA_LAYER, REFERENCE_LINE_LAYER, EXTENDED_ANNOTATION_LAYER, REFERENCE_LINE], + types: [EXTENDED_DATA_LAYER, REFERENCE_LINE_LAYER, REFERENCE_LINE], help: i18n.translate('expressionXY.layeredXyVis.layers.help', { defaultMessage: 'Layers of visual series', }), multi: true, }, + annotations: { + types: ['event_annotations_result'], + help: i18n.translate('expressionXY.layeredXyVis.annotations.help', { + defaultMessage: 'Annotations', + }), + }, splitColumnAccessor: { types: ['vis_dimension', 'string'], help: strings.getSplitColumnAccessorHelp(), diff --git a/src/plugins/chart_expressions/expression_xy/common/expression_functions/xy_vis.test.ts b/src/plugins/chart_expressions/expression_xy/common/expression_functions/xy_vis.test.ts index 0b81682eb4381d..7e6afa0dd23a7b 100644 --- a/src/plugins/chart_expressions/expression_xy/common/expression_functions/xy_vis.test.ts +++ b/src/plugins/chart_expressions/expression_xy/common/expression_functions/xy_vis.test.ts @@ -18,7 +18,7 @@ describe('xyVis', () => { const { layerId, layerType, table, type, ...restLayerArgs } = sampleLayer; const result = await xyVisFunction.fn( data, - { ...rest, ...restLayerArgs, referenceLines: [], annotationLayers: [] }, + { ...rest, ...restLayerArgs, referenceLines: [] }, createMockExecutionContext() ); @@ -53,7 +53,6 @@ describe('xyVis', () => { ...{ ...sampleLayer, markSizeAccessor: 'b' }, markSizeRatio: 0, referenceLines: [], - annotationLayers: [], }, createMockExecutionContext() ) @@ -67,7 +66,6 @@ describe('xyVis', () => { ...{ ...sampleLayer, markSizeAccessor: 'b' }, markSizeRatio: 101, referenceLines: [], - annotationLayers: [], }, createMockExecutionContext() ) @@ -86,7 +84,6 @@ describe('xyVis', () => { ...restLayerArgs, minTimeBarInterval: '1q', referenceLines: [], - annotationLayers: [], }, createMockExecutionContext() ) @@ -105,7 +102,6 @@ describe('xyVis', () => { ...restLayerArgs, minTimeBarInterval: '1h', referenceLines: [], - annotationLayers: [], }, createMockExecutionContext() ) @@ -124,7 +120,6 @@ describe('xyVis', () => { ...restLayerArgs, addTimeMarker: true, referenceLines: [], - annotationLayers: [], }, createMockExecutionContext() ) @@ -144,7 +139,7 @@ describe('xyVis', () => { ...rest, ...restLayerArgs, referenceLines: [], - annotationLayers: [], + splitRowAccessor, }, createMockExecutionContext() @@ -165,7 +160,7 @@ describe('xyVis', () => { ...rest, ...restLayerArgs, referenceLines: [], - annotationLayers: [], + splitColumnAccessor, }, createMockExecutionContext() @@ -185,7 +180,7 @@ describe('xyVis', () => { ...rest, ...restLayerArgs, referenceLines: [], - annotationLayers: [], + markSizeRatio: 5, }, createMockExecutionContext() @@ -207,7 +202,7 @@ describe('xyVis', () => { ...rest, ...restLayerArgs, referenceLines: [], - annotationLayers: [], + seriesType: 'bar', showLines: true, }, @@ -230,7 +225,7 @@ describe('xyVis', () => { ...rest, ...restLayerArgs, referenceLines: [], - annotationLayers: [], + isHistogram: true, xScaleType: 'time', xAxisConfig: { @@ -257,7 +252,7 @@ describe('xyVis', () => { ...rest, ...restLayerArgs, referenceLines: [], - annotationLayers: [], + xAxisConfig: { type: 'xAxisConfig', extent: { @@ -287,7 +282,7 @@ describe('xyVis', () => { ...rest, ...restLayerArgs, referenceLines: [], - annotationLayers: [], + xAxisConfig: { type: 'xAxisConfig', extent: { type: 'axisExtentConfig', mode: 'dataBounds' }, @@ -308,7 +303,7 @@ describe('xyVis', () => { ...rest, ...restLayerArgs, referenceLines: [], - annotationLayers: [], + isHistogram: true, xAxisConfig: { type: 'xAxisConfig', diff --git a/src/plugins/chart_expressions/expression_xy/common/expression_functions/xy_vis.ts b/src/plugins/chart_expressions/expression_xy/common/expression_functions/xy_vis.ts index 9db238a117b756..0b00525e3c9147 100644 --- a/src/plugins/chart_expressions/expression_xy/common/expression_functions/xy_vis.ts +++ b/src/plugins/chart_expressions/expression_xy/common/expression_functions/xy_vis.ts @@ -7,7 +7,7 @@ */ import { XyVisFn } from '../types'; -import { XY_VIS, REFERENCE_LINE, ANNOTATION_LAYER } from '../constants'; +import { XY_VIS, REFERENCE_LINE } from '../constants'; import { strings } from '../i18n'; import { commonXYArgs } from './common_xy_args'; import { commonDataLayerArgs } from './common_data_layer_args'; @@ -39,11 +39,6 @@ export const xyVisFunction: XyVisFn = { help: strings.getReferenceLinesHelp(), multi: true, }, - annotationLayers: { - types: [ANNOTATION_LAYER], - help: strings.getAnnotationLayerHelp(), - multi: true, - }, splitColumnAccessor: { types: ['vis_dimension', 'string'], help: strings.getSplitColumnAccessorHelp(), diff --git a/src/plugins/chart_expressions/expression_xy/common/expression_functions/xy_vis_fn.ts b/src/plugins/chart_expressions/expression_xy/common/expression_functions/xy_vis_fn.ts index 2808b861c6df85..defda933784de1 100644 --- a/src/plugins/chart_expressions/expression_xy/common/expression_functions/xy_vis_fn.ts +++ b/src/plugins/chart_expressions/expression_xy/common/expression_functions/xy_vis_fn.ts @@ -63,7 +63,6 @@ export const xyVisFn: XyVisFn['fn'] = async (data, args, handlers) => { const { referenceLines = [], - annotationLayers = [], // data_layer args seriesType, accessors, @@ -101,7 +100,6 @@ export const xyVisFn: XyVisFn['fn'] = async (data, args, handlers) => { const layers: XYLayerConfig[] = [ ...appendLayerIds(dataLayers, 'dataLayers'), ...appendLayerIds(referenceLines, 'referenceLines'), - ...appendLayerIds(annotationLayers, 'annotationLayers'), ]; logDatatable(data, layers, handlers, args.splitColumnAccessor, args.splitRowAccessor); diff --git a/src/plugins/chart_expressions/expression_xy/common/index.ts b/src/plugins/chart_expressions/expression_xy/common/index.ts index da4c969f47a0c0..b39002c8549cb8 100755 --- a/src/plugins/chart_expressions/expression_xy/common/index.ts +++ b/src/plugins/chart_expressions/expression_xy/common/index.ts @@ -34,7 +34,7 @@ export type { DataLayerConfig, FittingFunction, AxisExtentConfig, - CollectiveConfig, + MergedAnnotation, LegendConfigResult, AxesSettingsConfig, XAxisConfigResult, diff --git a/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts b/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts index 0970cec985d308..43d05eda09b237 100644 --- a/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts +++ b/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts @@ -215,7 +215,6 @@ export interface XYArgs extends DataLayerArgs { emphasizeFitting?: boolean; valueLabels: ValueLabelMode; referenceLines: ReferenceLineConfigResult[]; - annotationLayers: AnnotationLayerConfigResult[]; fittingFunction?: FittingFunction; fillOpacity?: number; hideEndzones?: boolean; @@ -233,12 +232,21 @@ export interface XYArgs extends DataLayerArgs { showTooltip: boolean; } +export interface ExpressionAnnotationsLayers { + layers: AnnotationLayerConfigResult[]; + datatable: Datatable; +} +export type ExpressionAnnotationResult = ExpressionAnnotationsLayers & { + type: 'event_annotations_result'; +}; + export interface LayeredXYArgs { legend: LegendConfigResult; endValue?: EndValue; emphasizeFitting?: boolean; valueLabels: ValueLabelMode; layers?: XYExtendedLayerConfigResult[]; + annotations?: ExpressionAnnotationResult; fittingFunction?: FittingFunction; fillOpacity?: number; hideEndzones?: boolean; @@ -279,6 +287,7 @@ export interface XYProps { orderBucketsBySum?: boolean; showTooltip: boolean; singleTable?: boolean; + annotations?: ExpressionAnnotationResult; } export interface AnnotationLayerArgs { @@ -326,7 +335,6 @@ export type XYExtendedLayerConfig = export type XYExtendedLayerConfigResult = | ExtendedDataLayerConfigResult | ReferenceLineLayerConfigResult - | ExtendedAnnotationLayerConfigResult | ReferenceLineConfigResult; export interface ExtendedReferenceLineDecorationConfig extends ReferenceLineArgs { diff --git a/src/plugins/chart_expressions/expression_xy/common/types/expression_renderers.ts b/src/plugins/chart_expressions/expression_xy/common/types/expression_renderers.ts index 8ee27ad7eab583..431c2721fa1c1a 100644 --- a/src/plugins/chart_expressions/expression_xy/common/types/expression_renderers.ts +++ b/src/plugins/chart_expressions/expression_xy/common/types/expression_renderers.ts @@ -24,9 +24,10 @@ export interface XYRender { value: XYChartProps; } -export interface CollectiveConfig extends Omit { +export interface MergedAnnotation extends Omit { timebucket: number; position: 'bottom'; icon?: AvailableAnnotationIcon | string; - customTooltipDetails?: AnnotationTooltipFormatter | undefined; + customTooltipDetails: AnnotationTooltipFormatter; + isGrouped: boolean; } diff --git a/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap b/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap index 43dbace37905c3..f178c870cffd83 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap +++ b/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap @@ -2,6 +2,7 @@ exports[`XYChart component annotations should render basic line annotation 1`] = ` } markerPosition="top" + placement="bottom" style={ Object { "line": Object { @@ -101,9 +105,9 @@ exports[`XYChart component annotations should render grouped line annotations pr dataValues={ Array [ Object { - "dataValue": 1647591900025, + "dataValue": 1647591917125, "details": "Event 1", - "header": 1647591900000, + "header": 1647591917100, }, ] } @@ -118,19 +122,19 @@ exports[`XYChart component annotations should render grouped line annotations pr "customTooltipDetails": [Function], "icon": "3", "id": "event1", + "isGrouped": true, "label": "Event 1", "lineStyle": "dashed", "lineWidth": 3, "position": "bottom", "textVisibility": undefined, "time": "2022-03-18T08:25:00.000Z", - "timebucket": 1647591900000, + "timebucket": 1647591917100, "type": "point", } } hasReducedPadding={true} isHorizontal={true} - label="Event 1" /> } markerBody={ @@ -139,6 +143,7 @@ exports[`XYChart component annotations should render grouped line annotations pr /> } markerPosition="top" + placement="bottom" style={ Object { "line": Object { @@ -161,9 +166,9 @@ exports[`XYChart component annotations should render grouped line annotations wi dataValues={ Array [ Object { - "dataValue": 1647591900025, + "dataValue": 1647591917125, "details": "Event 1", - "header": 1647591900000, + "header": 1647591917100, }, ] } @@ -178,19 +183,19 @@ exports[`XYChart component annotations should render grouped line annotations wi "customTooltipDetails": [Function], "icon": "2", "id": "event1", + "isGrouped": true, "label": "Event 1", "lineStyle": "solid", "lineWidth": 1, "position": "bottom", "textVisibility": undefined, "time": "2022-03-18T08:25:00.000Z", - "timebucket": 1647591900000, + "timebucket": 1647591917100, "type": "point", } } hasReducedPadding={true} isHorizontal={true} - label="Event 1" /> } markerBody={ @@ -199,6 +204,7 @@ exports[`XYChart component annotations should render grouped line annotations wi /> } markerPosition="top" + placement="bottom" style={ Object { "line": Object { @@ -214,6 +220,7 @@ exports[`XYChart component annotations should render grouped line annotations wi exports[`XYChart component annotations should render simplified annotations when simpleView is true 1`] = ` ( +
+ + {hasIcon(icon) && ( + + + + )} + {label} + +
+); + +const TooltipAnnotationDetails = ({ + row, + extraFields, + isGrouped, +}: { + row: PointEventAnnotationRow; + extraFields: Array<{ + key: string; + name: string; + formatter: FieldFormat | undefined; + }>; + isGrouped?: boolean; +}) => { + return ( +
+ + {isGrouped &&
{moment(row.time).format('YYYY-MM-DD, hh:mm:ss')}
} + +
+ {extraFields.map((field) => ( +
+ {field.name}:{' '} + {field.formatter ? field.formatter.convert(row[field.key]) : row[field.key]} +
+ ))} +
+
+
+ ); +}; + +const getExtraFields = ( + row: PointEventAnnotationRow, + formatFactory: FormatFactory, + columns: DatatableColumn[] | undefined +) => { + return Object.keys(row) + .filter((key) => key.startsWith('field:')) + .map((key) => { + const columnFormatter = columns?.find((c) => c.id === key)?.meta?.params; + return { + key, + name: key.replace('field:', ''), + formatter: columnFormatter && formatFactory(columnFormatter), + }; + }); +}; + const createCustomTooltipDetails = ( - config: ManualPointEventAnnotationArgs[], - formatter?: FieldFormat - ): AnnotationTooltipFormatter | undefined => + rows: PointEventAnnotationRow[], + formatFactory: FormatFactory, + columns: DatatableColumn[] | undefined + ): AnnotationTooltipFormatter => () => { + const groupedConfigs = groupBy(rows, 'id'); + const lastElement = rows[rows.length - 1]; return ( -
- {config.map(({ icon, label, time, color }) => ( -
- - {hasIcon(icon) && ( - - - - )} - {label} - - {formatter?.convert(time) || String(time)} +
+ {Object.values(groupedConfigs).map((group) => { + const firstElement = group[0]; + const extraFields = getExtraFields(firstElement, formatFactory, columns); + + return ( +
+ + + {group.map((row, index) => ( + <> + {index > 0 && ( + <> + + + + + )} + 1} + row={row} + extraFields={extraFields} + /> + + ))} + +
+ ); + })} + {lastElement.skippedCount && ( +
+
- ))} + )}
); }; @@ -109,10 +217,12 @@ export const OUTSIDE_RECT_ANNOTATION_WIDTH = 8; export const OUTSIDE_RECT_ANNOTATION_WIDTH_SUGGESTION = 2; export const getAnnotationsGroupedByInterval = ( - annotations: ManualPointEventAnnotationRow[], - formatter?: FieldFormat + annotations: PointEventAnnotationRow[], + configs: EventAnnotationOutput[] | undefined, + columns: DatatableColumn[] | undefined, + formatFactory: FormatFactory ) => { - const visibleGroupedConfigs = annotations.reduce>( + const visibleGroupedConfigs = annotations.reduce>( (acc, current) => { const timebucket = moment(current.timebucket).valueOf(); return { @@ -122,24 +232,36 @@ export const getAnnotationsGroupedByInterval = ( }, {} ); - let collectiveConfig: CollectiveConfig; - return Object.entries(visibleGroupedConfigs).map(([timebucket, configArr]) => { - collectiveConfig = { - ...configArr[0], - icon: configArr[0].icon || 'triangle', + return Object.entries(visibleGroupedConfigs).map(([timebucket, rowsPerBucket]) => { + const firstRow = rowsPerBucket[0]; + + const config = configs?.find((c) => c.id === firstRow.id); + const textField = config && 'textField' in config && config?.textField; + const columnFormatter = columns?.find((c) => c.id === `field:${textField}`)?.meta?.params; + const formatter = columnFormatter && formatFactory(columnFormatter); + const label = + textField && formatter && `field:${textField}` in firstRow + ? formatter.convert(firstRow[`field:${textField}`]) + : firstRow.label; + const mergedAnnotation: MergedAnnotation = { + ...firstRow, + label, + icon: firstRow.icon || 'triangle', timebucket: Number(timebucket), position: 'bottom', + customTooltipDetails: createCustomTooltipDetails(rowsPerBucket, formatFactory, columns), + isGrouped: false, }; - if (configArr.length > 1) { - const commonStyles = getCommonStyles(configArr); - collectiveConfig = { - ...collectiveConfig, + if (rowsPerBucket.length > 1) { + const commonStyles = getCommonStyles(rowsPerBucket); + return { + ...mergedAnnotation, ...commonStyles, - icon: String(configArr.length), - customTooltipDetails: createCustomTooltipDetails(configArr, formatter), + isGrouped: true, + icon: String(rowsPerBucket.length), }; } - return collectiveConfig; + return mergedAnnotation; }); }; @@ -161,20 +283,10 @@ export const Annotations = ({ <> {groupedLineAnnotations.map((annotation) => { const markerPositionVertical = Position.Top; - const markerPosition = isHorizontal - ? mapVerticalToHorizontalPlacement(markerPositionVertical) - : markerPositionVertical; const hasReducedPadding = paddingMap[markerPositionVertical] === LINES_MARKER_SIZE; - const id = snakeCase(`${annotation.id}-${annotation.time}`); - const { timebucket, time } = annotation; - const isGrouped = Boolean(annotation.customTooltipDetails); - const header = - formatter?.convert(isGrouped ? timebucket : time) || - moment(isGrouped ? timebucket : time).toISOString(); + const { timebucket, time, isGrouped, id: configId } = annotation; const strokeWidth = simpleView ? 1 : annotation.lineWidth || 1; - const dataValue = isGrouped - ? moment(isBarChart && minInterval ? timebucket + minInterval / 2 : timebucket).valueOf() - : moment(time).valueOf(); + const id = snakeCase(`${configId}-${time}`); return ( @@ -197,21 +309,34 @@ export const Annotations = ({ !simpleView ? ( ) : undefined } - markerPosition={markerPosition} + markerPosition={ + isHorizontal + ? mapVerticalToHorizontalPlacement(markerPositionVertical) + : markerPositionVertical + } dataValues={[ { - dataValue, - header, + dataValue: isGrouped + ? moment( + isBarChart && minInterval ? timebucket + minInterval / 2 : timebucket + ).valueOf() + : moment(time).valueOf(), + header: + formatter?.convert(isGrouped ? timebucket : time) || + moment(isGrouped ? timebucket : time).toISOString(), details: annotation.label, }, ]} customTooltipDetails={annotation.customTooltipDetails} + placement={'bottom'} style={{ line: { strokeWidth, diff --git a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.test.tsx b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.test.tsx index 387d1a077a7475..279e1e846ef85a 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.test.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.test.tsx @@ -54,13 +54,8 @@ import { sampleLayer, } from '../../common/__mocks__'; import { XYChart, XYChartRenderProps } from './xy_chart'; -import { - CommonXYAnnotationLayerConfig, - ExtendedDataLayerConfig, - XYProps, -} from '../../common/types'; +import { ExtendedDataLayerConfig, XYProps, AnnotationLayerConfigResult } from '../../common/types'; import { DataLayers } from './data_layers'; -import { Annotations } from './annotations'; import { SplitChart } from './split_chart'; import { LegendSize } from '@kbn/visualizations-plugin/common'; @@ -3068,12 +3063,18 @@ describe('XYChart component', () => { label: 'Event range', type: 'manual_range_event_annotation' as const, }; + const configToRowHelper = (config: EventAnnotationOutput) => { + return { + ...config, + timebucket: 1647591917100, + type: config.type === 'manual_point_event_annotation' ? 'point' : 'range', + }; + }; const createLayerWithAnnotations = ( annotations: EventAnnotationOutput[] = [defaultLineStaticAnnotation] - ): CommonXYAnnotationLayerConfig => ({ + ): AnnotationLayerConfigResult => ({ type: 'annotationLayer', layerType: LayerTypes.ANNOTATIONS, - layerId: 'annotation', annotations, }); function sampleArgsWithAnnotations(annotationLayers = [createLayerWithAnnotations()]) { @@ -3081,7 +3082,16 @@ describe('XYChart component', () => { return { args: { ...args, - layers: [dateHistogramLayer, ...annotationLayers], + layers: [dateHistogramLayer], + annotations: { + type: 'event_annotations_result' as const, + layers: annotationLayers, + datatable: { + type: 'datatable' as const, + columns: [], + rows: annotationLayers.flatMap((l) => l.annotations.map(configToRowHelper)), + }, + }, }, }; } @@ -3102,7 +3112,7 @@ describe('XYChart component', () => { const { args } = sampleArgsWithAnnotations([ createLayerWithAnnotations([defaultLineStaticAnnotation, defaultRangeStaticAnnotation]), ]); - (args.layers[1] as CommonXYAnnotationLayerConfig).simpleView = true; + args.annotations.layers[0].simpleView = true; const component = mount(); expect(component.find('LineAnnotation')).toMatchSnapshot(); expect(component.find('RectAnnotation')).toMatchSnapshot(); @@ -3135,7 +3145,7 @@ describe('XYChart component', () => { // checking tooltip const renderLinks = mount(
{groupedAnnotation.prop('customTooltipDetails')!()}
); expect(renderLinks.text()).toEqual( - ' Event 1 2022-03-18T08:25:00.000Z Event 3 2022-03-18T08:25:00.001Z Event 2 2022-03-18T08:25:00.020Z' + ' Event 12022-03-18, 04:25:002022-03-18, 04:25:002022-03-18, 04:25:00' ); }); @@ -3161,28 +3171,6 @@ describe('XYChart component', () => { // styles are default because they are different for both annotations expect(groupedAnnotation).toMatchSnapshot(); }); - test('should not render hidden annotations', () => { - const { args } = sampleArgsWithAnnotations([ - createLayerWithAnnotations([ - customLineStaticAnnotation, - { ...customLineStaticAnnotation, time: '2022-03-18T08:30:00.020Z', label: 'Event 2' }, - { - ...customLineStaticAnnotation, - time: '2022-03-18T08:35:00.001Z', - label: 'Event 3', - isHidden: true, - }, - defaultRangeStaticAnnotation, - { ...defaultRangeStaticAnnotation, label: 'range', isHidden: true }, - ]), - ]); - const component = mount(); - const lineAnnotations = component.find(LineAnnotation); - const rectAnnotations = component.find(Annotations).find(RectAnnotation); - - expect(lineAnnotations.length).toEqual(2); - expect(rectAnnotations.length).toEqual(1); - }); }); describe('split chart', () => { diff --git a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx index 62f67549f7df6e..9fb415308635e9 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx @@ -29,19 +29,13 @@ import { XYChartElementEvent, } from '@elastic/charts'; import { partition } from 'lodash'; -import moment from 'moment'; import { IconType } from '@elastic/eui'; import { PaletteRegistry } from '@kbn/coloring'; -import { Datatable, DatatableRow, RenderMode } from '@kbn/expressions-plugin/common'; +import { Datatable, RenderMode } from '@kbn/expressions-plugin/common'; import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; import { EmptyPlaceholder, LegendToggle } from '@kbn/charts-plugin/public'; import { EventAnnotationServiceType } from '@kbn/event-annotation-plugin/public'; -import { - ManualPointEventAnnotationRow, - ManualRangeEventAnnotationOutput, - ManualPointEventAnnotationOutput, - ManualRangeEventAnnotationRow, -} from '@kbn/event-annotation-plugin/common'; +import { PointEventAnnotationRow } from '@kbn/event-annotation-plugin/common'; import { ChartsPluginSetup, ChartsPluginStart, useActiveCursor } from '@kbn/charts-plugin/public'; import { MULTILAYER_TIME_AXIS_STYLE } from '@kbn/charts-plugin/common'; import { @@ -61,11 +55,9 @@ import type { ExtendedReferenceLineDecorationConfig, XYChartProps, AxisExtentConfigResult, - CommonXYAnnotationLayerConfig, } from '../../common/types'; import { isHorizontalChart, - getAnnotationsLayers, getDataLayers, AxisConfiguration, getAxisPosition, @@ -192,49 +184,6 @@ function createSplitPoint( export const XYChartReportable = React.memo(XYChart); -// TODO: remove this function when we start using fetch_event_annotation expression -const convertToAnnotationsTable = ( - layers: CommonXYAnnotationLayerConfig[], - minInterval?: number, - firstTimestamp?: number -) => { - return layers - .flatMap(({ annotations }) => - annotations.filter( - (a): a is ManualPointEventAnnotationOutput | ManualRangeEventAnnotationOutput => - !a.isHidden && 'time' in a - ) - ) - .sort((a, b) => moment(a.time).valueOf() - moment(b.time).valueOf()) - .map((a) => { - const timebucket = getRoundedTimestamp(moment(a.time).valueOf(), firstTimestamp, minInterval); - if (a.type === 'manual_point_event_annotation') { - const pointRow: ManualPointEventAnnotationRow = { - ...a, - type: 'point', - timebucket: moment(timebucket).toISOString(), - }; - return pointRow; - } - const rangeRow: ManualRangeEventAnnotationRow = { - ...a, - type: 'range', - }; - return rangeRow; - }); -}; - -export const sortByTime = (a: DatatableRow, b: DatatableRow) => { - return 'time' in a && 'time' in b ? a.time.localeCompare(b.time) : 0; -}; - -const getRoundedTimestamp = (timestamp: number, firstTimestamp?: number, minInterval?: number) => { - if (!firstTimestamp || !minInterval) { - return timestamp; - } - return timestamp - ((timestamp - firstTimestamp) % minInterval); -}; - export function XYChart({ args, data, @@ -267,6 +216,7 @@ export function XYChart({ splitColumnAccessor, splitRowAccessor, singleTable, + annotations, } = args; const chartRef = useRef(null); const chartTheme = chartsThemeService.useChartsTheme(); @@ -447,25 +397,18 @@ export function XYChart({ }; const referenceLineLayers = getReferenceLayers(layers); - - const annotationsLayers = getAnnotationsLayers(layers); - const firstTable = dataLayers[0]?.table; - - const columnId = dataLayers[0]?.xAccessor - ? getColumnByAccessor(dataLayers[0]?.xAccessor, firstTable.columns)?.id - : null; - - const annotations = convertToAnnotationsTable( - annotationsLayers, - minInterval, - columnId ? firstTable.rows[0]?.[columnId] : undefined + const [rangeAnnotations, lineAnnotations] = partition( + annotations?.datatable.rows, + isRangeAnnotation ); - const [rangeAnnotations, lineAnnotations] = partition(annotations, isRangeAnnotation); + const annotationsConfigs = annotations?.layers.flatMap((l) => l.annotations); const groupedLineAnnotations = getAnnotationsGroupedByInterval( - lineAnnotations as ManualPointEventAnnotationRow[], - xAxisFormatter + lineAnnotations as PointEventAnnotationRow[], + annotationsConfigs, + annotations?.datatable.columns, + formatFactory ); const visualConfigs = [ @@ -483,7 +426,10 @@ export function XYChart({ ...groupedLineAnnotations, ].filter(Boolean); - const shouldHideDetails = annotationsLayers.length > 0 ? annotationsLayers[0].simpleView : false; + const shouldHideDetails = + annotations?.layers && annotations.layers.length > 0 + ? annotations?.layers[0].simpleView + : false; const linesPaddings = !shouldHideDetails ? getLinesCausedPaddings(visualConfigs, yAxesMap, shouldRotate) : {}; diff --git a/src/plugins/chart_expressions/expression_xy/public/helpers/annotations.tsx b/src/plugins/chart_expressions/expression_xy/public/helpers/annotations.tsx index c4aebbfb969023..132c88e4f863dc 100644 --- a/src/plugins/chart_expressions/expression_xy/public/helpers/annotations.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/helpers/annotations.tsx @@ -12,7 +12,7 @@ import classnames from 'classnames'; import type { IconPosition, ReferenceLineDecorationConfig, - CollectiveConfig, + MergedAnnotation, } from '../../common/types'; import { getBaseIconPlacement } from '../components'; import { hasIcon, iconSet } from './icon'; @@ -27,16 +27,16 @@ type PartialReferenceLineDecorationConfig = Pick< position?: Position; }; -type PartialCollectiveConfig = Pick; +type PartialMergedAnnotation = Pick; const isExtendedDecorationConfig = ( - config: PartialReferenceLineDecorationConfig | PartialCollectiveConfig | undefined + config: PartialReferenceLineDecorationConfig | PartialMergedAnnotation | undefined ): config is PartialReferenceLineDecorationConfig => (config as PartialReferenceLineDecorationConfig)?.iconPosition ? true : false; // Note: it does not take into consideration whether the reference line is in view or not export const getLinesCausedPaddings = ( - visualConfigs: Array, + visualConfigs: Array, axesMap: AxesMap, shouldRotate: boolean ) => { diff --git a/src/plugins/chart_expressions/expression_xy/public/helpers/visualization.ts b/src/plugins/chart_expressions/expression_xy/public/helpers/visualization.ts index 87d27d30badb23..c75c4ee54ffe6c 100644 --- a/src/plugins/chart_expressions/expression_xy/public/helpers/visualization.ts +++ b/src/plugins/chart_expressions/expression_xy/public/helpers/visualization.ts @@ -57,10 +57,3 @@ const isAnnotationLayerCommon = ( export const isAnnotationsLayer = ( layer: CommonXYLayerConfig ): layer is CommonXYAnnotationLayerConfig => isAnnotationLayerCommon(layer); - -export const getAnnotationsLayers = ( - layers: CommonXYLayerConfig[] -): CommonXYAnnotationLayerConfig[] => - (layers || []).filter((layer): layer is CommonXYAnnotationLayerConfig => - isAnnotationsLayer(layer) - ); diff --git a/src/plugins/chart_expressions/expression_xy/public/plugin.ts b/src/plugins/chart_expressions/expression_xy/public/plugin.ts index 6de052b3921498..2de8dcd3d1e583 100755 --- a/src/plugins/chart_expressions/expression_xy/public/plugin.ts +++ b/src/plugins/chart_expressions/expression_xy/public/plugin.ts @@ -31,6 +31,7 @@ import { referenceLineDecorationConfigFunction, } from '../common/expression_functions'; import { GetStartDepsFn, getXyChartRenderer } from './expression_renderers'; +import { eventAnnotationsResult } from '../common/expression_functions/event_annotations_result'; export interface XYPluginStartDependencies { data: DataPublicPluginStart; @@ -63,6 +64,7 @@ export class ExpressionXyPlugin { expressions.registerFunction(xAxisConfigFunction); expressions.registerFunction(annotationLayerFunction); expressions.registerFunction(extendedAnnotationLayerFunction); + expressions.registerFunction(eventAnnotationsResult); expressions.registerFunction(referenceLineFunction); expressions.registerFunction(referenceLineLayerFunction); expressions.registerFunction(xyVisFunction); diff --git a/src/plugins/chart_expressions/expression_xy/server/plugin.ts b/src/plugins/chart_expressions/expression_xy/server/plugin.ts index f0e0fc141302ab..b6175774ac515e 100755 --- a/src/plugins/chart_expressions/expression_xy/server/plugin.ts +++ b/src/plugins/chart_expressions/expression_xy/server/plugin.ts @@ -25,6 +25,7 @@ import { extendedAnnotationLayerFunction, } from '../common/expression_functions'; import { SetupDeps } from './types'; +import { eventAnnotationsResult } from '../common/expression_functions/event_annotations_result'; export class ExpressionXyPlugin implements Plugin @@ -39,6 +40,7 @@ export class ExpressionXyPlugin expressions.registerFunction(axisExtentConfigFunction); expressions.registerFunction(annotationLayerFunction); expressions.registerFunction(extendedAnnotationLayerFunction); + expressions.registerFunction(eventAnnotationsResult); expressions.registerFunction(referenceLineFunction); expressions.registerFunction(referenceLineLayerFunction); expressions.registerFunction(xyVisFunction); diff --git a/src/plugins/charts/public/static/components/index.ts b/src/plugins/charts/public/static/components/index.ts index ea621c68e450aa..cc23b32e05ff2d 100644 --- a/src/plugins/charts/public/static/components/index.ts +++ b/src/plugins/charts/public/static/components/index.ts @@ -14,6 +14,7 @@ export { EmptyPlaceholder } from './empty_placeholder'; export { useCommonChartStyles } from './common_chart_styles'; export * from './endzones'; +export * from './warnings'; /** * The Lazily-loaded `ColorPicker` component. Consumers should use `React.Suspense` or diff --git a/src/plugins/charts/public/static/components/warnings.tsx b/src/plugins/charts/public/static/components/warnings.tsx new file mode 100644 index 00000000000000..9681cef1d6acea --- /dev/null +++ b/src/plugins/charts/public/static/components/warnings.tsx @@ -0,0 +1,52 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { EuiButtonEmpty, EuiHorizontalRule, EuiPopover, EuiText } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { euiThemeVars } from '@kbn/ui-theme'; +import React, { useState } from 'react'; + +export function Warnings({ warnings }: { warnings: React.ReactNode[] }) { + const [open, setOpen] = useState(false); + if (warnings.length === 0) return null; + return ( + <> + setOpen(false)} + button={ + setOpen(!open)} size="xs"> + {i18n.translate('charts.warning.warningLabel', { + defaultMessage: + '{numberWarnings, number} {numberWarnings, plural, one {warning} other {warnings}}', + values: { + numberWarnings: warnings.length, + }, + })} + + } + > +
+ {warnings.map((w, i) => ( + +
+ {w} +
+ {i < warnings.length - 1 && } +
+ ))} +
+
+ + ); +} diff --git a/src/plugins/data/common/search/aggs/buckets/index.ts b/src/plugins/data/common/search/aggs/buckets/index.ts index 4019e2d5b2aa0d..9d7819157e1890 100644 --- a/src/plugins/data/common/search/aggs/buckets/index.ts +++ b/src/plugins/data/common/search/aggs/buckets/index.ts @@ -29,6 +29,7 @@ export * from './lib/cidr_mask'; export * from './lib/date_range'; export * from './lib/ip_range'; export * from './lib/time_buckets/calc_auto_interval'; +export { TimeBuckets } from './lib/time_buckets'; export * from './migrate_include_exclude_format'; export * from './range_fn'; export * from './range'; diff --git a/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/table.tsx b/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/table.tsx index a83c1e98179ae2..bbb00b574076a5 100644 --- a/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/table.tsx +++ b/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/table.tsx @@ -23,6 +23,7 @@ import { EuiTablePagination, EuiSelectableMessage, EuiI18n, + useIsWithinBreakpoints, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; @@ -108,6 +109,8 @@ export const DocViewerTable = ({ onAddColumn, onRemoveColumn, }: DocViewRenderProps) => { + const showActionsInsideTableCell = useIsWithinBreakpoints(['xl'], true); + const { storage, uiSettings, fieldFormats } = useDiscoverServices(); const showMultiFields = uiSettings.get(SHOW_MULTIFIELDS); const currentDataViewId = dataView.id!; @@ -266,7 +269,11 @@ export const DocViewerTable = ({ const headers = [ !isSingleDocView && ( - + + {panels[0].items.map((item) => ( + + + + + + ))} + + ); + } + return ( { + return { + name: 'fetch_event_annotation', + aliases: [], + type: 'fetch_event_annotation', + inputTypes: ['null'], + help: i18n.translate('eventAnnotation.fetch.description', { + defaultMessage: 'Event annotation fetch', + }), + args: { + group: { + types: ['event_annotation_group'], + help: i18n.translate('eventAnnotation.group.args.annotationGroups', { + defaultMessage: 'Annotation group', + }), + multi: true, + }, + }, + fn: (input, args) => { + return { + type: 'fetch_event_annotation', + group: args.group, + }; + }, + }; +} diff --git a/src/plugins/event_annotation/common/fetch_event_annotations/fetch_event_annotations_fn.ts b/src/plugins/event_annotation/common/fetch_event_annotations/fetch_event_annotations_fn.ts index 66b470aa0afb02..d5ea46a4f33677 100644 --- a/src/plugins/event_annotation/common/fetch_event_annotations/fetch_event_annotations_fn.ts +++ b/src/plugins/event_annotation/common/fetch_event_annotations/fetch_event_annotations_fn.ts @@ -23,7 +23,6 @@ export const getFetchEventAnnotationsMeta: () => Omit< }), args: { groups: { - required: true, types: ['event_annotation_group'], help: i18n.translate('eventAnnotation.fetchEventAnnotations.args.annotationConfigs', { defaultMessage: 'Annotation configs', diff --git a/src/plugins/event_annotation/common/fetch_event_annotations/request_event_annotations.ts b/src/plugins/event_annotation/common/fetch_event_annotations/request_event_annotations.ts index 1f734b0182d6e2..e7127bf500ab58 100644 --- a/src/plugins/event_annotation/common/fetch_event_annotations/request_event_annotations.ts +++ b/src/plugins/event_annotation/common/fetch_event_annotations/request_event_annotations.ts @@ -6,17 +6,17 @@ * Side Public License, v 1. */ -import { defer, firstValueFrom } from 'rxjs'; +import { defer, lastValueFrom } from 'rxjs'; import { partition } from 'lodash'; import { AggsStart, - DataViewsContract, + DataView, DataViewSpec, ExpressionValueSearchContext, parseEsInterval, AggConfigs, - IndexPatternExpressionType, } from '@kbn/data-plugin/common'; + import { ExecutionContext } from '@kbn/expressions-plugin/common'; import moment from 'moment'; import { ESCalendarInterval, ESFixedInterval, roundDateToESInterval } from '@elastic/charts'; @@ -26,6 +26,7 @@ import { IUiSettingsClient } from '@kbn/core-ui-settings-browser'; import { handleRequest } from './handle_request'; import { ANNOTATIONS_PER_BUCKET, + getCalculatedInterval, isInRange, isManualAnnotation, isManualPointAnnotation, @@ -45,9 +46,9 @@ interface ManualGroup { interface QueryGroup { type: 'query'; annotations: QueryPointEventAnnotationOutput[]; - allFields?: string[]; - dataView: IndexPatternExpressionType; timeField: string; + dataView: DataView; + allFields?: string[]; } export function getTimeZone(uiSettings: IUiSettingsClient) { @@ -58,6 +59,7 @@ export function getTimeZone(uiSettings: IUiSettingsClient) { return configuredTimeZone; } +const emptyDatatable = { rows: [], columns: [], type: 'datatable' }; export const requestEventAnnotations = ( input: ExpressionValueSearchContext | null, @@ -71,20 +73,39 @@ export const requestEventAnnotations = ( getStartDependencies: () => Promise ) => { return defer(async () => { + if (!input?.timeRange || !args.groups) { + return emptyDatatable; + } const { aggs, dataViews, searchSource, getNow, uiSettings } = await getStartDependencies(); + const interval = getCalculatedInterval(uiSettings, args.interval, input?.timeRange); + if (!interval) { + return emptyDatatable; + } + + const uniqueDataViewsToLoad = args.groups + .map((g) => g.dataView.value) + .reduce((acc, current) => { + if (acc.find((el) => el.id === current.id)) return acc; + return [...acc, current]; + }, []); + + const loadedDataViews = await Promise.all( + uniqueDataViewsToLoad.map((dataView) => dataViews.create(dataView, true)) + ); + const [manualGroups, queryGroups] = partition( - regroupForRequestOptimization(args, input), + regroupForRequestOptimization(args, input, loadedDataViews), isManualSubGroup ); const manualAnnotationDatatableRows = manualGroups.length - ? convertManualToDatatableRows(manualGroups[0], args.interval, getTimeZone(uiSettings)) + ? convertManualToDatatableRows(manualGroups[0], interval, getTimeZone(uiSettings)) : []; if (!queryGroups.length) { return manualAnnotationDatatableRows.length ? wrapRowsInDatatable(manualAnnotationDatatableRows) - : null; + : emptyDatatable; } const createEsaggsSingleRequest = async ({ @@ -92,11 +113,11 @@ export const requestEventAnnotations = ( aggConfigs, timeFields, }: { - dataView: any; + dataView: DataView; aggConfigs: AggConfigs; timeFields: string[]; }) => - firstValueFrom( + lastValueFrom( handleRequest({ aggs: aggConfigs, indexPattern: dataView, @@ -113,12 +134,7 @@ export const requestEventAnnotations = ( }) ); - const esaggsGroups = await prepareEsaggsForQueryGroups( - queryGroups, - args.interval, - dataViews, - aggs - ); + const esaggsGroups = await prepareEsaggsForQueryGroups(queryGroups, interval, aggs); const allQueryAnnotationsConfigs = queryGroups.flatMap((group) => group.annotations); @@ -169,23 +185,9 @@ const convertManualToDatatableRows = ( const prepareEsaggsForQueryGroups = async ( queryGroups: QueryGroup[], interval: string, - dataViews: DataViewsContract, aggs: AggsStart ) => { - const uniqueDataViewsToLoad = queryGroups - .map((g) => g.dataView.value) - .reduce((acc, current) => { - if (acc.find((el) => el.id === current.id)) return acc; - return [...acc, current]; - }, []); - - const loadedDataViews = await Promise.all( - uniqueDataViewsToLoad.map((dataView) => dataViews.create(dataView, true)) - ); - return queryGroups.map((group) => { - const dataView = loadedDataViews.find((dv) => dv.id === group.dataView.value.id)!; - const annotationsFilters = { type: 'agg_type', value: { @@ -260,9 +262,12 @@ const prepareEsaggsForQueryGroups = async ( ...fieldsTopMetric, ]; - const aggConfigs = aggs.createAggConfigs(dataView, aggregations?.map((agg) => agg.value) ?? []); + const aggConfigs = aggs.createAggConfigs( + group.dataView, + aggregations?.map((agg) => agg.value) ?? [] + ); return { - esaggsParams: { dataView, aggConfigs, timeFields: [group.timeField] }, + esaggsParams: { dataView: group.dataView, aggConfigs, timeFields: [group.timeField] }, fieldsColIdMap: group.allFields?.reduce>( (acc, fieldName, i) => ({ @@ -278,15 +283,12 @@ const prepareEsaggsForQueryGroups = async ( function regroupForRequestOptimization( { groups }: FetchEventAnnotationsArgs, - input: ExpressionValueSearchContext | null + input: ExpressionValueSearchContext | null, + loadedDataViews: DataView[] ) { const outputGroups = groups .map((g) => { return g.annotations.reduce>((acc, current) => { - if (current.isHidden) { - return acc; - } - if (isManualAnnotation(current)) { if (!isInRange(current, input?.timeRange)) { return acc; @@ -297,7 +299,14 @@ function regroupForRequestOptimization( (acc.manual as ManualGroup).annotations.push(current); return acc; } else { - const key = `${g.dataView.value.id}-${current.timeField}`; + const dataView = loadedDataViews.find((dv) => dv.id === g.dataView.value.id)!; + + const timeField = + current.timeField ?? + (dataView.timeFieldName || + dataView.fields.find((field) => field.type === 'date' && field.displayName)?.name); + + const key = `${g.dataView.value.id}-${timeField}`; const subGroup = acc[key] as QueryGroup; if (subGroup) { let allFields = [...(subGroup.allFields || []), ...(current.extraFields || [])]; @@ -321,8 +330,8 @@ function regroupForRequestOptimization( ...acc, [key]: { type: 'query', - dataView: g.dataView, - timeField: current.timeField, + dataView, + timeField: timeField!, allFields, annotations: [current], }, diff --git a/src/plugins/event_annotation/common/fetch_event_annotations/types.ts b/src/plugins/event_annotation/common/fetch_event_annotations/types.ts index d323814e988953..79921cd2e13994 100644 --- a/src/plugins/event_annotation/common/fetch_event_annotations/types.ts +++ b/src/plugins/event_annotation/common/fetch_event_annotations/types.ts @@ -17,7 +17,9 @@ import { ExpressionFunctionDefinition, Datatable } from '@kbn/expressions-plugin import { IUiSettingsClient } from '@kbn/core-ui-settings-browser'; import { EventAnnotationGroupOutput } from '../event_annotation_group'; -export type FetchEventAnnotationsOutput = Observable; +export type FetchEventAnnotationsOutput = Observable< + Datatable | { rows: never[]; columns: never[]; type: string } +>; export interface FetchEventAnnotationsArgs { groups: EventAnnotationGroupOutput[]; diff --git a/src/plugins/event_annotation/common/fetch_event_annotations/utils.ts b/src/plugins/event_annotation/common/fetch_event_annotations/utils.ts index 9f53d2ca452add..caf6055c607933 100644 --- a/src/plugins/event_annotation/common/fetch_event_annotations/utils.ts +++ b/src/plugins/event_annotation/common/fetch_event_annotations/utils.ts @@ -6,10 +6,12 @@ * Side Public License, v 1. */ -import { TimeRange } from '@kbn/data-plugin/common'; +import { TimeBuckets, TimeRange, UI_SETTINGS } from '@kbn/data-plugin/common'; import { Datatable, DatatableColumn, DatatableRow } from '@kbn/expressions-plugin/common'; import { omit, pick } from 'lodash'; +import dateMath from '@kbn/datemath'; import moment from 'moment'; +import { IUiSettingsClient } from '@kbn/core-ui-settings-browser'; import { ManualEventAnnotationOutput, ManualPointEventAnnotationOutput, @@ -41,15 +43,70 @@ export const isManualAnnotation = ( ): annotation is ManualPointEventAnnotationOutput | ManualRangeEventAnnotationOutput => isRangeAnnotation(annotation) || isManualPointAnnotation(annotation); +function toAbsoluteDate(date: string) { + const parsed = dateMath.parse(date); + return parsed ? parsed.toDate() : undefined; +} + +export function toAbsoluteDates(range: TimeRange) { + const fromDate = dateMath.parse(range.from); + const toDate = dateMath.parse(range.to, { roundUp: true }); + + if (!fromDate || !toDate) { + return; + } + + return { + from: fromDate.toDate(), + to: toDate.toDate(), + }; +} + +export const getCalculatedInterval = ( + uiSettings: IUiSettingsClient, + usedInterval: string, + timeRange?: TimeRange +) => { + const dates = timeRange && toAbsoluteDates(timeRange); + if (!dates) { + return; + } + const buckets = new TimeBuckets({ + 'histogram:maxBars': uiSettings.get(UI_SETTINGS.HISTOGRAM_MAX_BARS), + 'histogram:barTarget': uiSettings.get(UI_SETTINGS.HISTOGRAM_BAR_TARGET), + dateFormat: uiSettings.get('dateFormat'), + 'dateFormat:scaled': uiSettings.get('dateFormat:scaled'), + }); + + buckets.setInterval(usedInterval); + buckets.setBounds({ + min: moment(dates.from), + max: moment(dates.to), + }); + + return buckets.getInterval().expression; +}; + export const isInRange = (annotation: ManualEventAnnotationOutput, timerange?: TimeRange) => { if (!timerange) { return false; } + const { from, to } = toAbsoluteDates(timerange) || {}; + if (!from || !to) { + return false; + } if (isRangeAnnotation(annotation)) { - return !(annotation.time >= timerange.to || annotation.endTime < timerange.from); + const time = toAbsoluteDate(annotation.time); + const endTime = toAbsoluteDate(annotation.endTime); + if (time && endTime) { + return !(time >= to || endTime < from); + } } if (isManualPointAnnotation(annotation)) { - return annotation.time >= timerange.from && annotation.time <= timerange.to; + const time = toAbsoluteDate(annotation.time); + if (time) { + return time >= from && time <= to; + } } return true; }; diff --git a/src/plugins/event_annotation/common/index.ts b/src/plugins/event_annotation/common/index.ts index c3badda900a0c7..779d0e13e78134 100644 --- a/src/plugins/event_annotation/common/index.ts +++ b/src/plugins/event_annotation/common/index.ts @@ -12,13 +12,12 @@ export type { ManualRangeEventAnnotationArgs, ManualRangeEventAnnotationOutput, ManualRangeEventAnnotationRow, - ManualPointEventAnnotationRow, + PointEventAnnotationRow, } from './manual_event_annotation/types'; export type { QueryPointEventAnnotationArgs, QueryPointEventAnnotationOutput, } from './query_point_event_annotation/types'; -export type { EventAnnotationArgs, EventAnnotationOutput } from './types'; export { manualPointEventAnnotation, manualRangeEventAnnotation } from './manual_event_annotation'; export { queryPointEventAnnotation } from './query_point_event_annotation'; export { eventAnnotationGroup } from './event_annotation_group'; @@ -27,8 +26,11 @@ export type { EventAnnotationGroupArgs } from './event_annotation_group'; export type { FetchEventAnnotationsArgs } from './fetch_event_annotations/types'; export type { EventAnnotationConfig, + EventAnnotationGroupConfig, + EventAnnotationArgs, RangeEventAnnotationConfig, PointInTimeEventAnnotationConfig, QueryPointEventAnnotationConfig, AvailableAnnotationIcon, + EventAnnotationOutput, } from './types'; diff --git a/src/plugins/event_annotation/common/manual_event_annotation/types.ts b/src/plugins/event_annotation/common/manual_event_annotation/types.ts index 235c0b03ff39d1..a74ba5723b61ed 100644 --- a/src/plugins/event_annotation/common/manual_event_annotation/types.ts +++ b/src/plugins/event_annotation/common/manual_event_annotation/types.ts @@ -17,13 +17,14 @@ export type ManualPointEventAnnotationOutput = ManualPointEventAnnotationArgs & type: 'manual_point_event_annotation'; }; -export type ManualPointEventAnnotationRow = { +export type PointEventAnnotationRow = { id: string; time: string; type: 'point'; timebucket: string; - skippedCount?: string; -} & PointStyleProps; + skippedCount?: number; +} & PointStyleProps & + Record; export type ManualRangeEventAnnotationArgs = { id: string; diff --git a/src/plugins/event_annotation/common/query_point_event_annotation/index.ts b/src/plugins/event_annotation/common/query_point_event_annotation/index.ts index 40f4ade0f95943..cb9ba882a9f891 100644 --- a/src/plugins/event_annotation/common/query_point_event_annotation/index.ts +++ b/src/plugins/event_annotation/common/query_point_event_annotation/index.ts @@ -38,7 +38,6 @@ export const queryPointEventAnnotation: ExpressionFunctionDefinition< help: i18n.translate('eventAnnotation.queryAnnotation.args.filter', { defaultMessage: `Annotation filter`, }), - required: true, }, extraFields: { multi: true, @@ -48,7 +47,6 @@ export const queryPointEventAnnotation: ExpressionFunctionDefinition< }), }, timeField: { - required: true, types: ['string'], help: i18n.translate('eventAnnotation.queryAnnotation.args.timeField', { defaultMessage: `The time field of the annotation`, diff --git a/src/plugins/event_annotation/common/query_point_event_annotation/types.ts b/src/plugins/event_annotation/common/query_point_event_annotation/types.ts index 0aa172017b36be..592c50a0621ce9 100644 --- a/src/plugins/event_annotation/common/query_point_event_annotation/types.ts +++ b/src/plugins/event_annotation/common/query_point_event_annotation/types.ts @@ -12,7 +12,7 @@ import { PointStyleProps } from '../types'; export type QueryPointEventAnnotationArgs = { id: string; filter: KibanaQueryOutput; - timeField: string; + timeField?: string; extraFields?: string[]; textField?: string; } & PointStyleProps; diff --git a/src/plugins/event_annotation/common/types.ts b/src/plugins/event_annotation/common/types.ts index 2e539a910124eb..76749bee5bc797 100644 --- a/src/plugins/event_annotation/common/types.ts +++ b/src/plugins/event_annotation/common/types.ts @@ -22,35 +22,39 @@ import { export type LineStyle = 'solid' | 'dashed' | 'dotted'; export type Fill = 'inside' | 'outside' | 'none'; -export type AnnotationType = 'manual'; +export type ManualAnnotationType = 'manual'; +export type QueryAnnotationType = 'query'; export type KeyType = 'point_in_time' | 'range'; export type AvailableAnnotationIcon = $Values; -export interface PointStyleProps { + +interface StyleSharedProps { label: string; color?: string; + isHidden?: boolean; +} + +export type PointStyleProps = StyleSharedProps & { icon?: AvailableAnnotationIcon; lineWidth?: number; lineStyle?: LineStyle; textVisibility?: boolean; - isHidden?: boolean; -} +}; export type PointInTimeEventAnnotationConfig = { id: string; + type: ManualAnnotationType; key: { type: 'point_in_time'; timestamp: string; }; } & PointStyleProps; -export interface RangeStyleProps { - label: string; - color?: string; +export type RangeStyleProps = StyleSharedProps & { outside?: boolean; - isHidden?: boolean; -} +}; export type RangeEventAnnotationConfig = { + type: ManualAnnotationType; id: string; key: { type: 'range'; @@ -63,9 +67,10 @@ export type StyleProps = PointStyleProps & RangeStyleProps; export type QueryPointEventAnnotationConfig = { id: string; + type: QueryAnnotationType; filter: KibanaQueryOutput; - timeField: string; - textField: string; + timeField?: string; + textField?: string; extraFields?: string[]; key: { type: 'point_in_time'; @@ -77,6 +82,11 @@ export type EventAnnotationConfig = | RangeEventAnnotationConfig | QueryPointEventAnnotationConfig; +export interface EventAnnotationGroupConfig { + annotations: EventAnnotationConfig[]; + indexPatternId: string; +} + export type EventAnnotationArgs = | ManualPointEventAnnotationArgs | ManualRangeEventAnnotationArgs diff --git a/src/plugins/event_annotation/public/event_annotation_service/helpers.ts b/src/plugins/event_annotation/public/event_annotation_service/helpers.ts index 280674c3dbfa23..afe64a5a47eb2e 100644 --- a/src/plugins/event_annotation/public/event_annotation_service/helpers.ts +++ b/src/plugins/event_annotation/public/event_annotation_service/helpers.ts @@ -14,6 +14,7 @@ import { QueryPointEventAnnotationConfig, } from '../../common'; export const defaultAnnotationColor = euiLightVars.euiColorAccent; +// Do not compute it live as dependencies will add tens of Kbs to the plugin export const defaultAnnotationRangeColor = `#F04E981A`; // defaultAnnotationColor with opacity 0.1 export const defaultAnnotationLabel = i18n.translate( @@ -38,5 +39,5 @@ export const isManualPointAnnotationConfig = ( export const isQueryAnnotationConfig = ( annotation?: EventAnnotationConfig ): annotation is QueryPointEventAnnotationConfig => { - return Boolean(annotation && 'filter' in annotation); + return Boolean(annotation && annotation.type === 'query'); }; diff --git a/src/plugins/event_annotation/public/event_annotation_service/service.test.ts b/src/plugins/event_annotation/public/event_annotation_service/service.test.ts new file mode 100644 index 00000000000000..0fea0e7c38ea76 --- /dev/null +++ b/src/plugins/event_annotation/public/event_annotation_service/service.test.ts @@ -0,0 +1,352 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { getEventAnnotationService } from './service'; +import { EventAnnotationServiceType } from './types'; + +describe('Event Annotation Service', () => { + let eventAnnotationService: EventAnnotationServiceType; + beforeAll(() => { + eventAnnotationService = getEventAnnotationService(); + }); + describe('toExpression', () => { + it('should work for an empty list', () => { + expect(eventAnnotationService.toExpression([])).toEqual([]); + }); + + it('should skip hidden annotations', () => { + expect( + eventAnnotationService.toExpression([ + { + id: 'myEvent', + type: 'manual', + key: { + type: 'point_in_time', + timestamp: '2022', + }, + label: 'Hello', + isHidden: true, + }, + { + id: 'myRangeEvent', + type: 'manual', + key: { + type: 'range', + timestamp: '2021', + endTimestamp: '2022', + }, + label: 'Hello Range', + isHidden: true, + }, + { + id: 'myEvent', + type: 'query', + timeField: '@timestamp', + key: { + type: 'point_in_time', + }, + label: 'Hello Range', + isHidden: true, + filter: { type: 'kibana_query', query: '', language: 'kuery' }, + }, + ]) + ).toEqual([]); + }); + it('should process manual point annotations', () => { + expect( + eventAnnotationService.toExpression([ + { + id: 'myEvent', + type: 'manual', + key: { + type: 'point_in_time', + timestamp: '2022', + }, + label: 'Hello', + }, + ]) + ).toEqual([ + { + type: 'expression', + chain: [ + { + type: 'function', + function: 'manual_point_event_annotation', + arguments: { + id: ['myEvent'], + time: ['2022'], + label: ['Hello'], + color: ['#f04e98'], + lineWidth: [1], + lineStyle: ['solid'], + icon: ['triangle'], + textVisibility: [false], + }, + }, + ], + }, + ]); + }); + it('should process manual range annotations', () => { + expect( + eventAnnotationService.toExpression([ + { + id: 'myEvent', + type: 'manual', + key: { + type: 'range', + timestamp: '2021', + endTimestamp: '2022', + }, + label: 'Hello', + }, + ]) + ).toEqual([ + { + type: 'expression', + chain: [ + { + type: 'function', + function: 'manual_range_event_annotation', + arguments: { + id: ['myEvent'], + time: ['2021'], + endTime: ['2022'], + label: ['Hello'], + color: ['#F04E981A'], + outside: [false], + }, + }, + ], + }, + ]); + }); + it('should process query based annotations', () => { + expect( + eventAnnotationService.toExpression([ + { + id: 'myEvent', + type: 'query', + timeField: '@timestamp', + key: { + type: 'point_in_time', + }, + label: 'Hello', + filter: { type: 'kibana_query', query: '', language: 'kuery' }, + }, + ]) + ).toEqual([ + { + type: 'expression', + chain: [ + { + type: 'function', + function: 'query_point_event_annotation', + arguments: { + id: ['myEvent'], + timeField: ['@timestamp'], + label: ['Hello'], + color: ['#f04e98'], + lineWidth: [1], + lineStyle: ['solid'], + icon: ['triangle'], + textVisibility: [false], + textField: [], + filter: [ + { + chain: [ + { + arguments: { + q: [''], + }, + function: 'kql', + type: 'function', + }, + ], + type: 'expression', + }, + ], + extraFields: [], + }, + }, + ], + }, + ]); + }); + it('should process mixed annotations', () => { + expect( + eventAnnotationService.toExpression([ + { + id: 'myEvent', + type: 'manual', + key: { + type: 'point_in_time', + timestamp: '2022', + }, + label: 'Hello', + }, + { + id: 'myRangeEvent', + type: 'manual', + key: { + type: 'range', + timestamp: '2021', + endTimestamp: '2022', + }, + label: 'Hello Range', + }, + { + id: 'myEvent', + type: 'query', + timeField: '@timestamp', + key: { + type: 'point_in_time', + }, + label: 'Hello', + filter: { type: 'kibana_query', query: '', language: 'kuery' }, + }, + ]) + ).toEqual([ + { + type: 'expression', + chain: [ + { + type: 'function', + function: 'manual_point_event_annotation', + arguments: { + id: ['myEvent'], + time: ['2022'], + label: ['Hello'], + color: ['#f04e98'], + lineWidth: [1], + lineStyle: ['solid'], + icon: ['triangle'], + textVisibility: [false], + }, + }, + ], + }, + { + type: 'expression', + chain: [ + { + type: 'function', + function: 'manual_range_event_annotation', + arguments: { + id: ['myRangeEvent'], + time: ['2021'], + endTime: ['2022'], + label: ['Hello Range'], + color: ['#F04E981A'], + outside: [false], + }, + }, + ], + }, + { + type: 'expression', + chain: [ + { + type: 'function', + function: 'query_point_event_annotation', + arguments: { + id: ['myEvent'], + timeField: ['@timestamp'], + label: ['Hello'], + color: ['#f04e98'], + lineWidth: [1], + lineStyle: ['solid'], + icon: ['triangle'], + textVisibility: [false], + textField: [], + filter: [ + { + chain: [ + { + arguments: { + q: [''], + }, + function: 'kql', + type: 'function', + }, + ], + type: 'expression', + }, + ], + extraFields: [], + }, + }, + ], + }, + ]); + }); + it.each` + textVisibility | textField | expected + ${'true'} | ${''} | ${''} + ${'false'} | ${''} | ${''} + ${'true'} | ${'myField'} | ${'myField'} + ${'false'} | ${''} | ${''} + `( + "should handle correctly textVisibility when set to '$textVisibility' and textField to '$textField'", + ({ textVisibility, textField, expected }) => { + expect( + eventAnnotationService.toExpression([ + { + id: 'myEvent', + type: 'query', + timeField: '@timestamp', + key: { + type: 'point_in_time', + }, + label: 'Hello', + filter: { type: 'kibana_query', query: '', language: 'kuery' }, + textVisibility, + textField, + }, + ]) + ).toEqual([ + { + type: 'expression', + chain: [ + { + type: 'function', + function: 'query_point_event_annotation', + arguments: { + id: ['myEvent'], + timeField: ['@timestamp'], + label: ['Hello'], + color: ['#f04e98'], + lineWidth: [1], + lineStyle: ['solid'], + icon: ['triangle'], + textVisibility: [textVisibility], + textField: expected ? [expected] : [], + filter: [ + { + chain: [ + { + arguments: { + q: [''], + }, + function: 'kql', + type: 'function', + }, + ], + type: 'expression', + }, + ], + extraFields: [], + }, + }, + ], + }, + ]); + } + ); + }); +}); diff --git a/src/plugins/event_annotation/public/event_annotation_service/service.tsx b/src/plugins/event_annotation/public/event_annotation_service/service.tsx index e657faca4afd78..41bf12c288cc12 100644 --- a/src/plugins/event_annotation/public/event_annotation_service/service.tsx +++ b/src/plugins/event_annotation/public/event_annotation_service/service.tsx @@ -6,38 +6,42 @@ * Side Public License, v 1. */ +import { partition } from 'lodash'; import { queryToAst } from '@kbn/data-plugin/common'; +import { ExpressionAstExpression } from '@kbn/expressions-plugin/common'; +import { EventAnnotationConfig } from '../../common'; import { EventAnnotationServiceType } from './types'; import { defaultAnnotationColor, defaultAnnotationRangeColor, defaultAnnotationLabel, + isRangeAnnotationConfig, isQueryAnnotationConfig, } from './helpers'; -import { EventAnnotationConfig } from '../../common'; -import { RangeEventAnnotationConfig } from '../../common/types'; export function hasIcon(icon: string | undefined): icon is string { return icon != null && icon !== 'empty'; } -const isRangeAnnotation = ( - annotation?: EventAnnotationConfig -): annotation is RangeEventAnnotationConfig => { - return Boolean(annotation && annotation?.key.type === 'range'); -}; - export function getEventAnnotationService(): EventAnnotationServiceType { - return { - toExpression: (annotation) => { - if (isRangeAnnotation(annotation)) { - const { label, isHidden, color, key, outside, id } = annotation; + const annotationsToExpression = (annotations: EventAnnotationConfig[]) => { + const visibleAnnotations = annotations.filter(({ isHidden }) => !isHidden); + const [queryBasedAnnotations, manualBasedAnnotations] = partition( + visibleAnnotations, + isQueryAnnotationConfig + ); + + const expressions = []; + + for (const annotation of manualBasedAnnotations) { + if (isRangeAnnotationConfig(annotation)) { + const { label, color, key, outside, id } = annotation; const { timestamp: time, endTimestamp: endTime } = key; - return { - type: 'expression', + expressions.push({ + type: 'expression' as const, chain: [ { - type: 'function', + type: 'function' as const, function: 'manual_range_event_annotation', arguments: { id: [id], @@ -46,57 +50,17 @@ export function getEventAnnotationService(): EventAnnotationServiceType { label: [label || defaultAnnotationLabel], color: [color || defaultAnnotationRangeColor], outside: [Boolean(outside)], - isHidden: [Boolean(isHidden)], - }, - }, - ], - }; - } else if (isQueryAnnotationConfig(annotation)) { - const { - id, - extraFields, - label, - isHidden, - color, - lineStyle, - lineWidth, - icon, - filter, - textVisibility, - timeField, - textField, - } = annotation; - return { - type: 'expression', - chain: [ - { - type: 'function', - function: 'query_point_event_annotation', - arguments: { - id: [id], - filter: filter ? [queryToAst(filter)] : [], - timeField: [timeField], - textField: [textField], - label: [label || defaultAnnotationLabel], - color: [color || defaultAnnotationColor], - lineWidth: [lineWidth || 1], - lineStyle: [lineStyle || 'solid'], - icon: hasIcon(icon) ? [icon] : ['triangle'], - textVisibility: [textVisibility || false], - isHidden: [Boolean(isHidden)], - extraFields: extraFields || [], }, }, ], - }; + }); } else { - const { label, isHidden, color, lineStyle, lineWidth, icon, key, textVisibility, id } = - annotation; - return { - type: 'expression', + const { label, color, lineStyle, lineWidth, icon, key, textVisibility, id } = annotation; + expressions.push({ + type: 'expression' as const, chain: [ { - type: 'function', + type: 'function' as const, function: 'manual_point_event_annotation', arguments: { id: [id], @@ -107,12 +71,106 @@ export function getEventAnnotationService(): EventAnnotationServiceType { lineStyle: [lineStyle || 'solid'], icon: hasIcon(icon) ? [icon] : ['triangle'], textVisibility: [textVisibility || false], - isHidden: [Boolean(isHidden)], }, }, ], - }; + }); } + } + + for (const annotation of queryBasedAnnotations) { + const { + id, + label, + color, + lineStyle, + lineWidth, + icon, + timeField, + textVisibility, + textField, + filter, + extraFields, + } = annotation; + expressions.push({ + type: 'expression' as const, + chain: [ + { + type: 'function' as const, + function: 'query_point_event_annotation', + arguments: { + id: [id], + timeField: timeField ? [timeField] : [], + label: [label || defaultAnnotationLabel], + color: [color || defaultAnnotationColor], + lineWidth: [lineWidth || 1], + lineStyle: [lineStyle || 'solid'], + icon: hasIcon(icon) ? [icon] : ['triangle'], + textVisibility: [textVisibility || false], + textField: textVisibility && textField ? [textField] : [], + filter: filter ? [queryToAst(filter)] : [], + extraFields: extraFields || [], + }, + }, + ], + }); + } + return expressions; + }; + return { + toExpression: annotationsToExpression, + toFetchExpression: ({ interval, groups }) => { + if (groups.length === 0) { + return []; + } + + const groupsExpressions = groups + .filter((g) => g.annotations.some((a) => !a.isHidden)) + .map(({ annotations, indexPatternId }): ExpressionAstExpression => { + const indexPatternExpression: ExpressionAstExpression = { + type: 'expression', + chain: [ + { + type: 'function', + function: 'indexPatternLoad', + arguments: { + id: [indexPatternId], + }, + }, + ], + }; + const annotationExpressions = annotationsToExpression(annotations); + return { + type: 'expression', + chain: [ + { + type: 'function', + function: 'event_annotation_group', + arguments: { + dataView: [indexPatternExpression], + annotations: [...annotationExpressions], + }, + }, + ], + }; + }); + + const fetchExpression: ExpressionAstExpression = { + type: 'expression', + chain: [ + { type: 'function', function: 'kibana', arguments: {} }, + { + type: 'function', + function: 'fetch_event_annotations', + arguments: { + interval: [interval], + groups: [...groupsExpressions], + }, + }, + ], + }; + + return [fetchExpression]; }, }; } diff --git a/src/plugins/event_annotation/public/event_annotation_service/types.ts b/src/plugins/event_annotation/public/event_annotation_service/types.ts index d5fcaa23107c82..cf3d759b7a324f 100644 --- a/src/plugins/event_annotation/public/event_annotation_service/types.ts +++ b/src/plugins/event_annotation/public/event_annotation_service/types.ts @@ -7,8 +7,12 @@ */ import { ExpressionAstExpression } from '@kbn/expressions-plugin/common/ast'; -import { EventAnnotationConfig } from '../../common'; +import { EventAnnotationConfig, EventAnnotationGroupConfig } from '../../common'; export interface EventAnnotationServiceType { - toExpression: (props: EventAnnotationConfig) => ExpressionAstExpression; + toExpression: (props: EventAnnotationConfig[]) => ExpressionAstExpression[]; + toFetchExpression: (props: { + interval: string; + groups: EventAnnotationGroupConfig[]; + }) => ExpressionAstExpression[]; } diff --git a/src/plugins/event_annotation/public/fetch_event_annotations/__snapshots__/fetch_event_annotations.test.ts.snap b/src/plugins/event_annotation/public/fetch_event_annotations/__snapshots__/fetch_event_annotations.test.ts.snap index daefa3f4af7cea..25729bfd5b80e0 100644 --- a/src/plugins/event_annotation/public/fetch_event_annotations/__snapshots__/fetch_event_annotations.test.ts.snap +++ b/src/plugins/event_annotation/public/fetch_event_annotations/__snapshots__/fetch_event_annotations.test.ts.snap @@ -37,6 +37,13 @@ Array [ "timebucket": "2022-07-05T04:30:00.000Z", "type": "point", }, + Object { + "id": "mann5", + "isHidden": true, + "time": "2022-07-05T05:55:00Z", + "timebucket": "2022-07-05T05:30:00.000Z", + "type": "point", + }, Object { "id": "mann1", "time": "2022-07-05T11:12:00Z", diff --git a/src/plugins/event_annotation/public/fetch_event_annotations/fetch_event_annotations.test.ts b/src/plugins/event_annotation/public/fetch_event_annotations/fetch_event_annotations.test.ts index aafb59a97d42a9..271ab5910afdf9 100644 --- a/src/plugins/event_annotation/public/fetch_event_annotations/fetch_event_annotations.test.ts +++ b/src/plugins/event_annotation/public/fetch_event_annotations/fetch_event_annotations.test.ts @@ -285,12 +285,12 @@ describe('getFetchEventAnnotations', () => { (startServices[1].data.dataViews.create as jest.Mock).mockClear(); (handleRequest as jest.Mock).mockClear(); }); - test('Returns null for empty groups', async () => { + test('Returns empty datatable for empty groups', async () => { const result = await runGetFetchEventAnnotations({ interval: '2h', groups: [], }); - expect(result).toEqual(null); + expect(result).toEqual({ columns: [], rows: [], type: 'datatable' }); }); describe('Manual annotations', () => { @@ -322,10 +322,6 @@ describe('getFetchEventAnnotations', () => { ], } as unknown as FetchEventAnnotationsArgs; - test(`Doesn't run dataViews.create for manual annotations groups only`, async () => { - await runGetFetchEventAnnotations(manualOnlyArgs); - expect(startServices[1].data.dataViews.create).not.toHaveBeenCalled(); - }); test('Sorts annotations by time, assigns correct timebuckets, filters out hidden and out of range annotations', async () => { const result = await runGetFetchEventAnnotations(manualOnlyArgs); expect(result!.rows).toMatchSnapshot(); @@ -340,7 +336,7 @@ describe('getFetchEventAnnotations', () => { { type: 'event_annotation_group', annotations: [manualAnnotationSamples.point1], - dataView1, + dataView: dataView1, }, { type: 'event_annotation_group', diff --git a/src/plugins/event_annotation/public/index.ts b/src/plugins/event_annotation/public/index.ts index 84245752e19fd7..58f6e2c7c9f22e 100644 --- a/src/plugins/event_annotation/public/index.ts +++ b/src/plugins/event_annotation/public/index.ts @@ -19,4 +19,5 @@ export { defaultAnnotationRangeColor, isRangeAnnotationConfig, isManualPointAnnotationConfig, + isQueryAnnotationConfig, } from './event_annotation_service/helpers'; diff --git a/src/plugins/interactive_setup/public/progress_indicator.tsx b/src/plugins/interactive_setup/public/progress_indicator.tsx index 51235f55fe6213..9fee7e6da71106 100644 --- a/src/plugins/interactive_setup/public/progress_indicator.tsx +++ b/src/plugins/interactive_setup/public/progress_indicator.tsx @@ -14,7 +14,7 @@ import useAsyncFn from 'react-use/lib/useAsyncFn'; import useTimeoutFn from 'react-use/lib/useTimeoutFn'; import type { IHttpFetchError } from '@kbn/core-http-browser'; -import type { StatusResponse } from '@kbn/core/types/status'; +import type { StatusResponse } from '@kbn/core-status-common-internal'; import { i18n } from '@kbn/i18n'; import { useKibana } from './use_kibana'; diff --git a/src/plugins/vis_types/table/kibana.json b/src/plugins/vis_types/table/kibana.json index 76ad6a7fec58fb..0d5d6066643ad9 100644 --- a/src/plugins/vis_types/table/kibana.json +++ b/src/plugins/vis_types/table/kibana.json @@ -6,7 +6,8 @@ "requiredPlugins": [ "expressions", "visualizations", - "fieldFormats" + "fieldFormats", + "usageCollection" ], "requiredBundles": [ "data", diff --git a/src/plugins/vis_types/table/public/plugin.ts b/src/plugins/vis_types/table/public/plugin.ts index ca05434c031e8e..9e246448eb0441 100644 --- a/src/plugins/vis_types/table/public/plugin.ts +++ b/src/plugins/vis_types/table/public/plugin.ts @@ -9,10 +9,7 @@ import type { CoreSetup, CoreStart, Plugin } from '@kbn/core/public'; import type { Plugin as ExpressionsPublicPlugin } from '@kbn/expressions-plugin/public'; import type { VisualizationsSetup } from '@kbn/visualizations-plugin/public'; -import type { - UsageCollectionSetup, - UsageCollectionStart, -} from '@kbn/usage-collection-plugin/public'; +import type { UsageCollectionStart } from '@kbn/usage-collection-plugin/public'; import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; import { setFormatService } from './services'; @@ -22,13 +19,12 @@ import { registerTableVis } from './register_vis'; export interface TablePluginSetupDependencies { expressions: ReturnType; visualizations: VisualizationsSetup; - usageCollection?: UsageCollectionSetup; } /** @internal */ export interface TablePluginStartDependencies { fieldFormats: FieldFormatsStart; - usageCollection?: UsageCollectionStart; + usageCollection: UsageCollectionStart; } /** @internal */ diff --git a/src/plugins/vis_types/table/public/services.ts b/src/plugins/vis_types/table/public/services.ts index 345c63474d1729..edc6969e389edc 100644 --- a/src/plugins/vis_types/table/public/services.ts +++ b/src/plugins/vis_types/table/public/services.ts @@ -7,11 +7,7 @@ */ import { createGetterSetter } from '@kbn/kibana-utils-plugin/public'; -import type { UsageCollectionStart } from '@kbn/usage-collection-plugin/public'; import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; export const [getFormatService, setFormatService] = createGetterSetter('FieldFormats'); - -export const [getUsageCollectionStart, setUsageCollectionStart] = - createGetterSetter('UsageCollection', false); diff --git a/src/plugins/vis_types/table/public/table_vis_renderer.tsx b/src/plugins/vis_types/table/public/table_vis_renderer.tsx index 0dc37543dc54e9..783cf49d063112 100644 --- a/src/plugins/vis_types/table/public/table_vis_renderer.tsx +++ b/src/plugins/vis_types/table/public/table_vis_renderer.tsx @@ -35,7 +35,7 @@ const extractContainerType = (context?: KibanaExecutionContext): string | undefi export const getTableVisRenderer: ( core: CoreStart, - usageCollection?: UsageCollectionStart + usageCollection: UsageCollectionStart ) => ExpressionRenderDefinition = (core, usageCollection) => ({ name: 'table_vis', reuseDomNode: true, @@ -51,7 +51,7 @@ export const getTableVisRenderer: ( const containerType = extractContainerType(handlers.getExecutionContext()); const visualizationType = 'agg_based'; - if (usageCollection && containerType) { + if (containerType) { const counterEvents = [ `render_${visualizationType}_table`, !visData.table ? `render_${visualizationType}_table_split` : undefined, diff --git a/src/plugins/vis_types/timeseries/kibana.json b/src/plugins/vis_types/timeseries/kibana.json index bf6a781de95253..9194743d3af6b7 100644 --- a/src/plugins/vis_types/timeseries/kibana.json +++ b/src/plugins/vis_types/timeseries/kibana.json @@ -4,7 +4,7 @@ "kibanaVersion": "kibana", "server": true, "ui": true, - "requiredPlugins": ["charts", "data", "expressions", "visualizations", "inspector", "dataViews", "fieldFormats"], + "requiredPlugins": ["charts", "data", "expressions", "visualizations", "inspector", "dataViews", "fieldFormats", "usageCollection"], "optionalPlugins": ["home"], "requiredBundles": ["unifiedSearch", "kibanaUtils", "kibanaReact", "fieldFormats"], "owner": { diff --git a/src/plugins/vis_types/timeseries/public/metrics_type.ts b/src/plugins/vis_types/timeseries/public/metrics_type.ts index edd4ac0297b3c2..012bdd35115f28 100644 --- a/src/plugins/vis_types/timeseries/public/metrics_type.ts +++ b/src/plugins/vis_types/timeseries/public/metrics_type.ts @@ -24,9 +24,9 @@ import { extractIndexPatternValues, isStringTypeIndexPattern, } from '../common/index_patterns_utils'; -import { TSVB_DEFAULT_COLOR } from '../common/constants'; +import { TSVB_DEFAULT_COLOR, UI_SETTINGS } from '../common/constants'; import { toExpressionAst } from './to_ast'; -import { getDataViewsStart } from './services'; +import { getDataViewsStart, getUISettings } from './services'; import type { TimeseriesVisDefaultParams, TimeseriesVisParams } from './types'; import type { IndexPatternValue, Panel } from '../common/types'; import { convertTSVBtoLensConfiguration } from './convert_to_lens'; @@ -176,5 +176,6 @@ export const metricsVisDefinition: VisTypeDefinition< requests: new RequestAdapter(), }), requiresSearch: true, + suppressWarnings: () => !getUISettings().get(UI_SETTINGS.ALLOW_CHECKING_FOR_FAILED_SHARDS), getUsedIndexPattern: getUsedIndexPatterns, }; diff --git a/src/plugins/vis_types/timeseries/public/plugin.ts b/src/plugins/vis_types/timeseries/public/plugin.ts index b784db9a92f868..8ca5a916a7ce3a 100644 --- a/src/plugins/vis_types/timeseries/public/plugin.ts +++ b/src/plugins/vis_types/timeseries/public/plugin.ts @@ -43,7 +43,7 @@ export interface MetricsPluginStartDependencies { fieldFormats: FieldFormatsStart; dataViews: DataViewsPublicPluginStart; charts: ChartsPluginStart; - usageCollection?: UsageCollectionStart; + usageCollection: UsageCollectionStart; } /** @internal */ @@ -77,8 +77,6 @@ export class MetricsPlugin implements Plugin { setDataStart(data); setDataViewsStart(dataViews); setCoreStart(core); - if (usageCollection) { - setUsageCollectionStart(usageCollection); - } + setUsageCollectionStart(usageCollection); } } diff --git a/src/plugins/vis_types/timeseries/public/request_handler.ts b/src/plugins/vis_types/timeseries/public/request_handler.ts index 2cf0e740178a94..24768dc10a17fa 100644 --- a/src/plugins/vis_types/timeseries/public/request_handler.ts +++ b/src/plugins/vis_types/timeseries/public/request_handler.ts @@ -10,7 +10,7 @@ import type { Adapters } from '@kbn/inspector-plugin/common'; import { KibanaContext } from '@kbn/data-plugin/public'; import { getTimezone } from './application/lib/get_timezone'; import { getUISettings, getDataStart, getCoreStart } from './services'; -import { ROUTES, UI_SETTINGS } from '../common/constants'; +import { ROUTES } from '../common/constants'; import type { TimeseriesVisParams } from './types'; import type { TimeseriesVisData } from '../common/types'; @@ -84,14 +84,6 @@ export const metricsRequestHandler = async ({ ?.start(query.label ?? key, { searchSessionId }) .json(query.body) .ok({ time: query.time, json: { rawResponse: query.response } }); - - if ( - query.response && - inspectorAdapters?.requests && - config.get(UI_SETTINGS.ALLOW_CHECKING_FOR_FAILED_SHARDS) - ) { - data.search.showWarnings(inspectorAdapters.requests); - } }); return visData; diff --git a/src/plugins/vis_types/timeseries/public/services.ts b/src/plugins/vis_types/timeseries/public/services.ts index 4b0e4082d0dc59..c68971e24822b6 100644 --- a/src/plugins/vis_types/timeseries/public/services.ts +++ b/src/plugins/vis_types/timeseries/public/services.ts @@ -31,4 +31,4 @@ export const [getI18n, setI18n] = createGetterSetter('I18n'); export const [getCharts, setCharts] = createGetterSetter('ChartsPluginStart'); export const [getUsageCollectionStart, setUsageCollectionStart] = - createGetterSetter('UsageCollection', false); + createGetterSetter('UsageCollection'); diff --git a/src/plugins/vis_types/vega/kibana.json b/src/plugins/vis_types/vega/kibana.json index 423f044aa3275c..5fbaabec722aa2 100644 --- a/src/plugins/vis_types/vega/kibana.json +++ b/src/plugins/vis_types/vega/kibana.json @@ -3,7 +3,7 @@ "version": "kibana", "server": true, "ui": true, - "requiredPlugins": ["data", "visualizations", "mapsEms", "expressions", "inspector", "dataViews"], + "requiredPlugins": ["data", "visualizations", "mapsEms", "expressions", "inspector", "dataViews", "usageCollection"], "optionalPlugins": ["home"], "requiredBundles": ["kibanaUtils", "kibanaReact", "visDefaultEditor"], "owner": { diff --git a/src/plugins/vis_types/vega/public/plugin.ts b/src/plugins/vis_types/vega/public/plugin.ts index db4d4a458458a3..54f319850d817e 100644 --- a/src/plugins/vis_types/vega/public/plugin.ts +++ b/src/plugins/vis_types/vega/public/plugin.ts @@ -58,7 +58,7 @@ export interface VegaPluginStartDependencies { data: DataPublicPluginStart; mapsEms: MapsEmsPluginPublicStart; dataViews: DataViewsPublicPluginStart; - usageCollection?: UsageCollectionStart; + usageCollection: UsageCollectionStart; } /** @internal */ @@ -104,9 +104,6 @@ export class VegaPlugin implements Plugin { setDataViews(dataViews); setDocLinks(core.docLinks); setMapsEms(mapsEms); - - if (usageCollection) { - setUsageCollectionStart(usageCollection); - } + setUsageCollectionStart(usageCollection); } } diff --git a/src/plugins/vis_types/vega/public/services.ts b/src/plugins/vis_types/vega/public/services.ts index a2bc3524ce022e..4b3e0ca72cdc32 100644 --- a/src/plugins/vis_types/vega/public/services.ts +++ b/src/plugins/vis_types/vega/public/services.ts @@ -34,4 +34,4 @@ export const getEnableExternalUrls = () => getInjectedVars().enableExternalUrls; export const [getDocLinks, setDocLinks] = createGetterSetter('docLinks'); export const [getUsageCollectionStart, setUsageCollectionStart] = - createGetterSetter('UsageCollection', false); + createGetterSetter('UsageCollection'); diff --git a/src/plugins/visualizations/kibana.json b/src/plugins/visualizations/kibana.json index 69b9eb6c2b0902..bf7f7f9cdff0e5 100644 --- a/src/plugins/visualizations/kibana.json +++ b/src/plugins/visualizations/kibana.json @@ -5,6 +5,7 @@ "ui": true, "requiredPlugins": [ "data", + "charts", "expressions", "fieldFormats", "uiActions", @@ -19,7 +20,7 @@ "dataViewEditor" ], "optionalPlugins": ["home", "share", "spaces", "savedObjectsTaggingOss"], - "requiredBundles": ["kibanaUtils", "savedSearch", "kibanaReact"], + "requiredBundles": ["kibanaUtils", "savedSearch", "kibanaReact", "charts"], "extraPublicDirs": ["common/constants", "common/utils", "common/expression_functions"], "owner": { "name": "Vis Editors", diff --git a/src/plugins/visualizations/public/embeddable/embeddables.scss b/src/plugins/visualizations/public/embeddable/embeddables.scss index 2a4d5c14a46a50..3b96abda035a21 100644 --- a/src/plugins/visualizations/public/embeddable/embeddables.scss +++ b/src/plugins/visualizations/public/embeddable/embeddables.scss @@ -19,6 +19,13 @@ } } +.visPanel__warnings { + position: absolute; + z-index: 2; + right: $euiSizeM; + bottom: $euiSizeM; +} + // OPTIONS MENU /** diff --git a/src/plugins/visualizations/public/embeddable/visualize_embeddable.tsx b/src/plugins/visualizations/public/embeddable/visualize_embeddable.tsx index d616f48083e008..fcdcede24409ea 100644 --- a/src/plugins/visualizations/public/embeddable/visualize_embeddable.tsx +++ b/src/plugins/visualizations/public/embeddable/visualize_embeddable.tsx @@ -18,6 +18,7 @@ import type { ErrorLike } from '@kbn/expressions-plugin/common'; import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; import { TimefilterContract } from '@kbn/data-plugin/public'; import type { DataView } from '@kbn/data-views-plugin/public'; +import { Warnings } from '@kbn/charts-plugin/public'; import { Adapters, AttributeService, @@ -115,6 +116,7 @@ export class VisualizeEmbeddable private expression?: ExpressionAstExpression; private vis: Vis; private domNode: any; + private warningDomNode: any; public readonly type = VISUALIZE_EMBEDDABLE_TYPE; private abortController?: AbortController; private readonly deps: VisualizeEmbeddableFactoryDeps; @@ -332,6 +334,31 @@ export class VisualizeEmbeddable return dirty; } + private handleWarnings() { + const warnings: React.ReactNode[] = []; + if (this.getInspectorAdapters()?.requests) { + this.deps + .start() + .plugins.data.search.showWarnings(this.getInspectorAdapters()!.requests!, (warning) => { + if ( + warning.type === 'shard_failure' && + warning.reason.type === 'unsupported_aggregation_on_downsampled_index' + ) { + warnings.push(warning.reason.reason || warning.message); + return true; + } + if (this.vis.type.suppressWarnings?.()) { + // if the vis type wishes to supress all warnings, return true so the default logic won't pick it up + return true; + } + }); + } + + if (this.warningDomNode) { + render(, this.warningDomNode); + } + } + // this is a hack to make editor still work, will be removed once we clean up editor // @ts-ignore hasInspector = () => Boolean(this.getInspectorAdapters()); @@ -347,6 +374,7 @@ export class VisualizeEmbeddable }; onContainerData = () => { + this.handleWarnings(); this.updateOutput({ ...this.getOutput(), loading: false, @@ -386,6 +414,11 @@ export class VisualizeEmbeddable div.className = `visualize panel-content panel-content--fullWidth`; domNode.appendChild(div); + const warningDiv = document.createElement('div'); + warningDiv.className = 'visPanel__warnings'; + domNode.appendChild(warningDiv); + this.warningDomNode = warningDiv; + this.domNode = div; super.render(this.domNode); @@ -532,6 +565,7 @@ export class VisualizeEmbeddable timeRange: this.timeRange, query: this.input.query, filters: this.input.filters, + disableShardWarnings: true, }, variables: { embeddableTitle: this.getTitle(), diff --git a/src/plugins/visualizations/public/vis_types/base_vis_type.ts b/src/plugins/visualizations/public/vis_types/base_vis_type.ts index 18dcacadcaeab0..1b0875f636af4b 100644 --- a/src/plugins/visualizations/public/vis_types/base_vis_type.ts +++ b/src/plugins/visualizations/public/vis_types/base_vis_type.ts @@ -40,6 +40,7 @@ export class BaseVisType { public readonly editorConfig; public hidden; public readonly requiresSearch; + public readonly suppressWarnings; public readonly hasPartialRows; public readonly hierarchicalData; public readonly setup; @@ -64,6 +65,7 @@ export class BaseVisType { this.title = opts.title; this.icon = opts.icon; this.image = opts.image; + this.suppressWarnings = opts.suppressWarnings; this.visConfig = defaultsDeep({}, opts.visConfig, { defaults: {} }); this.editorConfig = defaultsDeep({}, opts.editorConfig, { collections: {} }); this.options = defaultsDeep({}, opts.options, defaultOptions); diff --git a/src/plugins/visualizations/public/vis_types/types.ts b/src/plugins/visualizations/public/vis_types/types.ts index ebcdcf594fdfda..45be7f08ca7112 100644 --- a/src/plugins/visualizations/public/vis_types/types.ts +++ b/src/plugins/visualizations/public/vis_types/types.ts @@ -214,6 +214,10 @@ export interface VisTypeDefinition { * It sets the vis type on a deprecated mode when is true */ readonly isDeprecated?: boolean; + /** + * If returns true, no warning toasts will be shown + */ + readonly suppressWarnings?: () => boolean; /** * Describes the experience group that the visualization belongs. * It can be on tools, aggregation based or promoted group. diff --git a/src/plugins/visualizations/tsconfig.json b/src/plugins/visualizations/tsconfig.json index 02eda42929b9fa..6a533c71facd7d 100644 --- a/src/plugins/visualizations/tsconfig.json +++ b/src/plugins/visualizations/tsconfig.json @@ -14,6 +14,7 @@ ], "references": [ { "path": "../../core/tsconfig.json" }, + { "path": "../charts/tsconfig.json" }, { "path": "../data/tsconfig.json" }, { "path": "../data_views/tsconfig.json" }, { "path": "../expressions/tsconfig.json" }, diff --git a/test/examples/search/warnings.ts b/test/examples/search/warnings.ts index 78aa042ce6ea66..05179aa926f86c 100644 --- a/test/examples/search/warnings.ts +++ b/test/examples/search/warnings.ts @@ -32,7 +32,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const testRollupIndex = 'sample-01-rollup'; const testRollupField = 'kubernetes.container.memory.usage.bytes'; const toastsSelector = '[data-test-subj=globalToastList] [data-test-subj=euiToastHeader]'; - const shardFailureType = 'unsupported_aggregation_on_rollup_index'; + const shardFailureType = 'unsupported_aggregation_on_downsampled_index'; const shardFailureReason = `Field [${testRollupField}] of type [aggregate_metric_double] is not supported for aggregation [percentiles]`; const getTestJson = async (tabTestSubj: string, codeTestSubj: string) => { diff --git a/test/functional/apps/console/_comments.ts b/test/functional/apps/console/_comments.ts index 9132e0f04b0c8d..32500352759762 100644 --- a/test/functional/apps/console/_comments.ts +++ b/test/functional/apps/console/_comments.ts @@ -15,8 +15,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const retry = getService('retry'); const PageObjects = getPageObjects(['common', 'console', 'header']); - // Failing: See https://github.com/elastic/kibana/issues/139295 - describe.skip('console app', function testComments() { + describe('console app', function testComments() { this.tags('includeFirefox'); before(async () => { log.debug('navigateTo console'); @@ -47,8 +46,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); } - // FLAKY: https://github.com/elastic/kibana/issues/138160 - describe.skip('with single line comments', async () => { + describe('with single line comments', async () => { await runTests( [ { @@ -129,6 +127,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { body: '{\n "query": \'\'', // E.g. using single quotes }, ], + async () => { expect(await PageObjects.console.hasInvalidSyntax()).to.be(true); } diff --git a/x-pack/packages/ml/agg_utils/kibana.jsonc b/x-pack/packages/ml/agg_utils/kibana.jsonc new file mode 100644 index 00000000000000..4bcfcbd8721a63 --- /dev/null +++ b/x-pack/packages/ml/agg_utils/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/ml-agg-utils", + "owner": "@elastic/ml-ui", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/x-pack/packages/ml/aiops_components/kibana.jsonc b/x-pack/packages/ml/aiops_components/kibana.jsonc new file mode 100644 index 00000000000000..3fc4f228e2b0f1 --- /dev/null +++ b/x-pack/packages/ml/aiops_components/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/aiops-components", + "owner": "@elastic/ml-ui", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/x-pack/packages/ml/aiops_utils/kibana.jsonc b/x-pack/packages/ml/aiops_utils/kibana.jsonc new file mode 100644 index 00000000000000..46d16f2cdc3342 --- /dev/null +++ b/x-pack/packages/ml/aiops_utils/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/aiops-utils", + "owner": "@elastic/ml-ui", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/x-pack/packages/ml/is_populated_object/kibana.jsonc b/x-pack/packages/ml/is_populated_object/kibana.jsonc new file mode 100644 index 00000000000000..44240b60c4198b --- /dev/null +++ b/x-pack/packages/ml/is_populated_object/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/ml-is-populated-object", + "owner": "@elastic/ml-ui", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/x-pack/packages/ml/string_hash/kibana.jsonc b/x-pack/packages/ml/string_hash/kibana.jsonc new file mode 100644 index 00000000000000..0986bb25375c56 --- /dev/null +++ b/x-pack/packages/ml/string_hash/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/ml-string-hash", + "owner": "@elastic/ml-ui", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/x-pack/plugins/aiops/kibana.json b/x-pack/plugins/aiops/kibana.json index 7c3a76deae6ee8..6648816b078433 100755 --- a/x-pack/plugins/aiops/kibana.json +++ b/x-pack/plugins/aiops/kibana.json @@ -12,11 +12,9 @@ "requiredPlugins": [ "charts", "data", - "discover", - "licensing", - "unifiedSearch" + "licensing" ], "optionalPlugins": [], - "requiredBundles": ["kibanaReact", "fieldFormats"], + "requiredBundles": ["fieldFormats"], "extraPublicDirs": ["common"] } diff --git a/x-pack/plugins/aiops/public/application/services/time_field_range.ts b/x-pack/plugins/aiops/public/application/services/time_field_range.ts index 380538f7236877..845ec7f71f5f27 100644 --- a/x-pack/plugins/aiops/public/application/services/time_field_range.ts +++ b/x-pack/plugins/aiops/public/application/services/time_field_range.ts @@ -10,7 +10,8 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; -import { getCoreStart } from '../../kibana_services'; + +import type { HttpStart } from '@kbn/core/public'; export interface GetTimeFieldRangeResponse { success: boolean; @@ -23,16 +24,17 @@ export async function getTimeFieldRange({ timeFieldName, query, runtimeMappings, + http, }: { index: string; timeFieldName?: string; query?: QueryDslQueryContainer; runtimeMappings?: estypes.MappingRuntimeFields; + http: HttpStart; }) { const body = JSON.stringify({ index, timeFieldName, query, runtimeMappings }); - const coreStart = getCoreStart(); - return await coreStart.http.fetch({ + return await http.fetch({ path: `/internal/file_upload/time_field_range`, method: 'POST', body, diff --git a/x-pack/plugins/aiops/public/components/date_picker_wrapper/date_picker_wrapper.tsx b/x-pack/plugins/aiops/public/components/date_picker_wrapper/date_picker_wrapper.tsx index 2072d7df7cfe64..605f130594bc88 100644 --- a/x-pack/plugins/aiops/public/components/date_picker_wrapper/date_picker_wrapper.tsx +++ b/x-pack/plugins/aiops/public/components/date_picker_wrapper/date_picker_wrapper.tsx @@ -16,8 +16,8 @@ import { EuiSuperDatePicker, OnRefreshProps } from '@elastic/eui'; import type { TimeRange } from '@kbn/es-query'; import { TimeHistoryContract, UI_SETTINGS } from '@kbn/data-plugin/public'; -import { useUrlState } from '../../hooks/url_state'; -import { useAiOpsKibana } from '../../kibana_context'; +import { useUrlState } from '../../hooks/use_url_state'; +import { useAiopsAppContext } from '../../hooks/use_aiops_app_context'; import { aiopsRefresh$ } from '../../application/services/timefilter_refresh_service'; interface TimePickerQuickRange { @@ -54,9 +54,8 @@ function updateLastRefresh(timeRange: OnRefreshProps) { } export const DatePickerWrapper: FC = () => { - const { services } = useAiOpsKibana(); - const config = services.uiSettings; - const { timefilter, history } = services.data.query.timefilter; + const { uiSettings, data } = useAiopsAppContext(); + const { timefilter, history } = data.query.timefilter; const [globalState, setGlobalState] = useUrlState('_g'); const getRecentlyUsedRanges = getRecentlyUsedRangesFactory(history); @@ -81,8 +80,8 @@ export const DatePickerWrapper: FC = () => { timefilter.isTimeRangeSelectorEnabled() ); - const dateFormat = config.get('dateFormat'); - const timePickerQuickRanges = config.get( + const dateFormat = uiSettings.get('dateFormat'); + const timePickerQuickRanges = uiSettings.get( UI_SETTINGS.TIMEPICKER_QUICK_RANGES ); diff --git a/x-pack/plugins/aiops/public/components/document_count_content/document_count_chart/document_count_chart.tsx b/x-pack/plugins/aiops/public/components/document_count_content/document_count_chart/document_count_chart.tsx index dfb94fe549d3bd..5f024ac393c506 100644 --- a/x-pack/plugins/aiops/public/components/document_count_content/document_count_chart/document_count_chart.tsx +++ b/x-pack/plugins/aiops/public/components/document_count_content/document_count_chart/document_count_chart.tsx @@ -29,7 +29,7 @@ import type { WindowParameters } from '@kbn/aiops-utils'; import { MULTILAYER_TIME_AXIS_STYLE } from '@kbn/charts-plugin/common'; import type { ChangePoint } from '@kbn/ml-agg-utils'; -import { useAiOpsKibana } from '../../../kibana_context'; +import { useAiopsAppContext } from '../../../hooks/use_aiops_app_context'; import { BrushBadge } from './brush_badge'; @@ -103,9 +103,7 @@ export const DocumentCountChart: FC = ({ changePoint, isBrushCleared, }) => { - const { - services: { data, uiSettings, fieldFormats, charts }, - } = useAiOpsKibana(); + const { data, uiSettings, fieldFormats, charts } = useAiopsAppContext(); const chartTheme = charts.theme.useChartsTheme(); const chartBaseTheme = charts.theme.useChartsBaseTheme(); diff --git a/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes_analysis.tsx b/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes_analysis.tsx index 063d27acff53e4..8e7907382175bc 100644 --- a/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes_analysis.tsx +++ b/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes_analysis.tsx @@ -19,7 +19,7 @@ import { FormattedMessage } from '@kbn/i18n-react'; import type { ChangePoint } from '@kbn/ml-agg-utils'; import type { Query } from '@kbn/es-query'; -import { useAiOpsKibana } from '../../kibana_context'; +import { useAiopsAppContext } from '../../hooks/use_aiops_app_context'; import { initialState, streamReducer } from '../../../common/api/stream_reducer'; import type { ApiExplainLogRateSpikes } from '../../../common/api'; @@ -53,8 +53,8 @@ export const ExplainLogRateSpikesAnalysis: FC onSelectedChangePoint, selectedChangePoint, }) => { - const { services } = useAiOpsKibana(); - const basePath = services.http?.basePath.get() ?? ''; + const { http } = useAiopsAppContext(); + const basePath = http.basePath.get() ?? ''; const [currentAnalysisWindowParameters, setCurrentAnalysisWindowParameters] = useState< WindowParameters | undefined diff --git a/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes_app_state.tsx b/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes_app_state.tsx index 56135d4eb7b737..9b9395721e5355 100644 --- a/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes_app_state.tsx +++ b/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes_app_state.tsx @@ -32,7 +32,9 @@ import { isRisonSerializationRequired, getNestedProperty, SetUrlState, -} from '../../hooks/url_state'; +} from '../../hooks/use_url_state'; +import type { AiopsAppDependencies } from '../../hooks/use_aiops_app_context'; +import { AiopsAppContext } from '../../hooks/use_aiops_app_context'; import { ExplainLogRateSpikesPage } from './explain_log_rate_spikes_page'; @@ -41,6 +43,8 @@ export interface ExplainLogRateSpikesAppStateProps { dataView: DataView; /** The saved search to analyze. */ savedSearch: SavedSearch | SavedSearchSavedObject | null; + /** App dependencies */ + appDependencies: AiopsAppDependencies; } const defaultSearchQuery = { @@ -69,6 +73,7 @@ export const restorableDefaults = getDefaultAiOpsListState(); export const ExplainLogRateSpikesAppState: FC = ({ dataView, savedSearch, + appDependencies, }) => { const history = useHistory(); const { search: urlSearchString } = useLocation(); @@ -157,8 +162,10 @@ export const ExplainLogRateSpikesAppState: FC } return ( - - - + + + + + ); }; diff --git a/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes_page.tsx b/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes_page.tsx index 3afea37406f054..bdc91175c29138 100644 --- a/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes_page.tsx +++ b/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes_page.tsx @@ -26,9 +26,9 @@ import { Filter, FilterStateStore, Query } from '@kbn/es-query'; import { FormattedMessage } from '@kbn/i18n-react'; import { SavedSearch } from '@kbn/discover-plugin/public'; -import { useAiOpsKibana } from '../../kibana_context'; +import { useAiopsAppContext } from '../../hooks/use_aiops_app_context'; import { SearchQueryLanguage, SavedSearchSavedObject } from '../../application/utils/search_utils'; -import { useUrlState, usePageUrlState, AppStateKey } from '../../hooks/url_state'; +import { useUrlState, usePageUrlState, AppStateKey } from '../../hooks/use_url_state'; import { useData } from '../../hooks/use_data'; import { FullTimeRangeSelector } from '../full_time_range_selector'; import { DocumentCountContent } from '../document_count_content/document_count_content'; @@ -55,8 +55,7 @@ export const ExplainLogRateSpikesPage: FC = ({ dataView, savedSearch, }) => { - const { services } = useAiOpsKibana(); - const { data: dataService } = services; + const { data: dataService } = useAiopsAppContext(); const [aiopsListState, setAiopsListState] = usePageUrlState(AppStateKey, restorableDefaults); const [globalState, setGlobalState] = useUrlState('_g'); diff --git a/x-pack/plugins/aiops/public/components/full_time_range_selector/full_time_range_selector.tsx b/x-pack/plugins/aiops/public/components/full_time_range_selector/full_time_range_selector.tsx index 7b0b54680b7b72..1e248552b84841 100644 --- a/x-pack/plugins/aiops/public/components/full_time_range_selector/full_time_range_selector.tsx +++ b/x-pack/plugins/aiops/public/components/full_time_range_selector/full_time_range_selector.tsx @@ -25,7 +25,7 @@ import { EuiToolTip, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { useAiOpsKibana } from '../../kibana_context'; +import { useAiopsAppContext } from '../../hooks/use_aiops_app_context'; import { setFullTimeRange } from './full_time_range_selector_service'; import { AIOPS_FROZEN_TIER_PREFERENCE, useStorage } from '../../hooks/use_storage'; @@ -52,16 +52,22 @@ export const FullTimeRangeSelector: FC = ({ callback, }) => { const { - services: { - notifications: { toasts }, - }, - } = useAiOpsKibana(); + http, + notifications: { toasts }, + } = useAiopsAppContext(); // wrapper around setFullTimeRange to allow for the calling of the optional callBack prop const setRange = useCallback( async (i: DataView, q?: QueryDslQueryContainer, excludeFrozenData?: boolean) => { try { - const fullTimeRange = await setFullTimeRange(timefilter, i, q, excludeFrozenData, toasts); + const fullTimeRange = await setFullTimeRange( + timefilter, + i, + toasts, + http, + q, + excludeFrozenData + ); if (typeof callback === 'function') { callback(fullTimeRange); } @@ -76,7 +82,7 @@ export const FullTimeRangeSelector: FC = ({ ); } }, - [callback, timefilter, toasts] + [callback, http, timefilter, toasts] ); const [isPopoverOpen, setPopover] = useState(false); diff --git a/x-pack/plugins/aiops/public/components/full_time_range_selector/full_time_range_selector_service.ts b/x-pack/plugins/aiops/public/components/full_time_range_selector/full_time_range_selector_service.ts index 8514e170aca283..f6d6488567f101 100644 --- a/x-pack/plugins/aiops/public/components/full_time_range_selector/full_time_range_selector_service.ts +++ b/x-pack/plugins/aiops/public/components/full_time_range_selector/full_time_range_selector_service.ts @@ -13,7 +13,7 @@ import { TimefilterContract } from '@kbn/data-plugin/public'; import dateMath from '@kbn/datemath'; import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; import { i18n } from '@kbn/i18n'; -import type { ToastsStart } from '@kbn/core/public'; +import type { ToastsStart, HttpStart } from '@kbn/core/public'; import { DataView } from '@kbn/data-views-plugin/public'; import { isPopulatedObject } from '@kbn/ml-is-populated-object'; import { getTimeFieldRange } from '../../application/services/time_field_range'; @@ -33,9 +33,10 @@ export interface TimeRange { export async function setFullTimeRange( timefilter: TimefilterContract, dataView: DataView, + toasts: ToastsStart, + http: HttpStart, query?: QueryDslQueryContainer, - excludeFrozenData?: boolean, - toasts?: ToastsStart + excludeFrozenData?: boolean ): Promise { const runtimeMappings = dataView.getRuntimeMappings(); const resp = await getTimeFieldRange({ @@ -43,6 +44,7 @@ export async function setFullTimeRange( timeFieldName: dataView.timeFieldName, query: excludeFrozenData ? addExcludeFrozenToQuery(query) : query, ...(isPopulatedObject(runtimeMappings) ? { runtimeMappings } : {}), + http, }); if (resp.start.epoch && resp.end.epoch) { @@ -51,7 +53,7 @@ export async function setFullTimeRange( to: moment(resp.end.epoch).toISOString(), }); } else { - toasts?.addWarning({ + toasts.addWarning({ title: i18n.translate('xpack.aiops.index.fullTimeRangeSelector.noResults', { defaultMessage: 'No results match your search criteria', }), diff --git a/x-pack/plugins/aiops/public/components/mini_histogram/mini_histogram.tsx b/x-pack/plugins/aiops/public/components/mini_histogram/mini_histogram.tsx index 2940983aaabbf0..ba1e54550ccb08 100644 --- a/x-pack/plugins/aiops/public/components/mini_histogram/mini_histogram.tsx +++ b/x-pack/plugins/aiops/public/components/mini_histogram/mini_histogram.tsx @@ -14,7 +14,7 @@ import { EuiLoadingChart, EuiTextColor } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import type { ChangePointHistogramItem } from '@kbn/ml-agg-utils'; -import { useAiOpsKibana } from '../../kibana_context'; +import { useAiopsAppContext } from '../../hooks/use_aiops_app_context'; import { useEuiTheme } from '../../hooks/use_eui_theme'; interface MiniHistogramProps { @@ -24,9 +24,7 @@ interface MiniHistogramProps { } export const MiniHistogram: FC = ({ chartData, isLoading, label }) => { - const { - services: { charts }, - } = useAiOpsKibana(); + const { charts } = useAiopsAppContext(); const euiTheme = useEuiTheme(); const defaultChartTheme = charts.theme.useChartsTheme(); diff --git a/x-pack/plugins/aiops/public/components/search_panel/search_panel.tsx b/x-pack/plugins/aiops/public/components/search_panel/search_panel.tsx index bac4268da6ab22..9388ba27af0b8a 100644 --- a/x-pack/plugins/aiops/public/components/search_panel/search_panel.tsx +++ b/x-pack/plugins/aiops/public/components/search_panel/search_panel.tsx @@ -12,8 +12,7 @@ import { Query, Filter } from '@kbn/es-query'; import type { TimeRange } from '@kbn/es-query'; import { DataView, DataViewField } from '@kbn/data-views-plugin/public'; import { SearchQueryLanguage } from '../../application/utils/search_utils'; -import { useAiOpsKibana } from '../../kibana_context'; -import { getPluginsStart } from '../../kibana_services'; +import { useAiopsAppContext } from '../../hooks/use_aiops_app_context'; import { createMergedEsQuery } from '../../application/utils/search_utils'; interface Props { dataView: DataView; @@ -40,15 +39,15 @@ export const SearchPanel: FC = ({ searchQueryLanguage, setSearchParams, }) => { - const { unifiedSearch } = getPluginsStart(); - const { SearchBar } = unifiedSearch?.ui; const { - services: { - uiSettings, - notifications: { toasts }, - data: { query: queryManager }, + uiSettings, + unifiedSearch: { + ui: { SearchBar }, }, - } = useAiOpsKibana(); + notifications: { toasts }, + data: { query: queryManager }, + } = useAiopsAppContext(); + // The internal state of the input query bar updated on every key stroke. const [searchInput, setSearchInput] = useState({ query: searchString || '', diff --git a/x-pack/plugins/aiops/public/components/spike_analysis_table/spike_analysis_table.tsx b/x-pack/plugins/aiops/public/components/spike_analysis_table/spike_analysis_table.tsx index b35fbe971b011d..8a65a938d38c92 100644 --- a/x-pack/plugins/aiops/public/components/spike_analysis_table/spike_analysis_table.tsx +++ b/x-pack/plugins/aiops/public/components/spike_analysis_table/spike_analysis_table.tsx @@ -6,6 +6,8 @@ */ import React, { FC, useCallback, useMemo, useState } from 'react'; +import { sortBy } from 'lodash'; + import { EuiBadge, EuiBasicTable, @@ -14,16 +16,17 @@ import { EuiTableSortingType, EuiToolTip, } from '@elastic/eui'; -import { sortBy } from 'lodash'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import { escapeKuery } from '@kbn/es-query'; import type { ChangePoint } from '@kbn/ml-agg-utils'; + +import { SEARCH_QUERY_LANGUAGE } from '../../application/utils/search_utils'; import { useEuiTheme } from '../../hooks/use_eui_theme'; +import { useAiopsAppContext } from '../../hooks/use_aiops_app_context'; + import { MiniHistogram } from '../mini_histogram'; -import { useAiOpsKibana } from '../../kibana_context'; -import { SEARCH_QUERY_LANGUAGE } from '../../application/utils/search_utils'; import { getFailedTransactionsCorrelationImpactLabel } from './get_failed_transactions_correlation_impact_label'; @@ -64,10 +67,7 @@ export const SpikeAnalysisTable: FC = ({ const [sortField, setSortField] = useState(DEFAULT_SORT_FIELD); const [sortDirection, setSortDirection] = useState<'asc' | 'desc'>(DEFAULT_SORT_DIRECTION); - const aiOpsKibana = useAiOpsKibana(); - const { - services: { application, share, data }, - } = aiOpsKibana; + const { application, share, data } = useAiopsAppContext(); const discoverLocator = useMemo( () => share.url.locators.get('DISCOVER_APP_LOCATOR'), diff --git a/x-pack/plugins/aiops/public/hooks/use_aiops_app_context.ts b/x-pack/plugins/aiops/public/hooks/use_aiops_app_context.ts new file mode 100644 index 00000000000000..3c44ae7bdb0a31 --- /dev/null +++ b/x-pack/plugins/aiops/public/hooks/use_aiops_app_context.ts @@ -0,0 +1,43 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { createContext, useContext } from 'react'; + +import type { IStorageWrapper } from '@kbn/kibana-utils-plugin/public'; + +import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; +import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public'; +import type { ChartsPluginStart } from '@kbn/charts-plugin/public'; +import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; +import type { SharePluginStart } from '@kbn/share-plugin/public'; +import type { CoreStart, CoreSetup, HttpStart, IUiSettingsClient } from '@kbn/core/public'; + +export interface AiopsAppDependencies { + application: CoreStart['application']; + data: DataPublicPluginStart; + charts: ChartsPluginStart; + fieldFormats: FieldFormatsStart; + http: HttpStart; + notifications: CoreSetup['notifications']; + storage: IStorageWrapper; + uiSettings: IUiSettingsClient; + unifiedSearch: UnifiedSearchPublicPluginStart; + share: SharePluginStart; +} + +export const AiopsAppContext = createContext(undefined); + +export const useAiopsAppContext = (): AiopsAppDependencies => { + const aiopsAppContext = useContext(AiopsAppContext); + + // if `undefined`, throw an error + if (aiopsAppContext === undefined) { + throw new Error('useAiopsAppContext was used outside of its Provider'); + } + + return aiopsAppContext; +}; diff --git a/x-pack/plugins/aiops/public/hooks/use_data.ts b/x-pack/plugins/aiops/public/hooks/use_data.ts index 0c3012c6603cee..471196334e15c5 100644 --- a/x-pack/plugins/aiops/public/hooks/use_data.ts +++ b/x-pack/plugins/aiops/public/hooks/use_data.ts @@ -16,7 +16,7 @@ import type { SavedSearch } from '@kbn/discover-plugin/public'; import { TimeBuckets } from '../../common/time_buckets'; -import { useAiOpsKibana } from '../kibana_context'; +import { useAiopsAppContext } from './use_aiops_app_context'; import { aiopsRefresh$ } from '../application/services/timefilter_refresh_service'; import type { DocumentStatsSearchStrategyParams } from '../get_document_stats'; import type { AiOpsIndexBasedAppState } from '../components/explain_log_rate_spikes/explain_log_rate_spikes_app_state'; @@ -27,7 +27,7 @@ import { import { useTimefilter } from './use_time_filter'; import { useDocumentCountStats } from './use_document_count_stats'; -import type { Dictionary } from './url_state'; +import type { Dictionary } from './use_url_state'; export const useData = ( { @@ -38,8 +38,12 @@ export const useData = ( onUpdate: (params: Dictionary) => void, selectedChangePoint?: ChangePoint ) => { - const { services } = useAiOpsKibana(); - const { uiSettings, data } = services; + const { + uiSettings, + data: { + query: { filterManager }, + }, + } = useAiopsAppContext(); const [lastRefresh, setLastRefresh] = useState(0); const [fieldStatsRequest, setFieldStatsRequest] = useState< DocumentStatsSearchStrategyParams | undefined @@ -47,12 +51,11 @@ export const useData = ( /** Prepare required params to pass to search strategy **/ const { searchQueryLanguage, searchString, searchQuery } = useMemo(() => { - const filterManager = data.query.filterManager; const searchData = getEsQueryFromSavedSearch({ dataView: currentDataView, uiSettings, savedSearch: currentSavedSearch, - filterManager: data.query.filterManager, + filterManager, }); if (searchData === undefined || aiopsListState.searchString !== '') { diff --git a/x-pack/plugins/aiops/public/hooks/use_document_count_stats.ts b/x-pack/plugins/aiops/public/hooks/use_document_count_stats.ts index 48929c25e800a9..1d443d98491b8f 100644 --- a/x-pack/plugins/aiops/public/hooks/use_document_count_stats.ts +++ b/x-pack/plugins/aiops/public/hooks/use_document_count_stats.ts @@ -12,7 +12,6 @@ import { i18n } from '@kbn/i18n'; import type { ToastsStart } from '@kbn/core/public'; import { stringHash } from '@kbn/ml-string-hash'; -import { useAiOpsKibana } from '../kibana_context'; import { extractErrorProperties } from '../application/utils/error_utils'; import { DocumentCountStats, @@ -21,6 +20,8 @@ import { DocumentStatsSearchStrategyParams, } from '../get_document_stats'; +import { useAiopsAppContext } from './use_aiops_app_context'; + export interface DocumentStats { totalCount: number; documentCountStats?: DocumentCountStats; @@ -59,11 +60,9 @@ export function useDocumentCountStats (uiSettings.get('theme:darkMode') ? euiThemeDark : euiThemeLight), diff --git a/x-pack/plugins/aiops/public/hooks/use_storage.ts b/x-pack/plugins/aiops/public/hooks/use_storage.ts index 59325a529728bd..c377a85b3e84c7 100644 --- a/x-pack/plugins/aiops/public/hooks/use_storage.ts +++ b/x-pack/plugins/aiops/public/hooks/use_storage.ts @@ -6,7 +6,7 @@ */ import { useCallback, useState } from 'react'; -import { useAiOpsKibana } from '../kibana_context'; +import { useAiopsAppContext } from './use_aiops_app_context'; export const AIOPS_FROZEN_TIER_PREFERENCE = 'aiops.frozenDataTierPreference'; @@ -22,9 +22,7 @@ export type AiOpsKey = keyof Exclude; * @param initValue */ export function useStorage(key: AiOpsKey, initValue?: T): [T, (value: T) => void] { - const { - services: { storage }, - } = useAiOpsKibana(); + const { storage } = useAiopsAppContext(); const [val, setVal] = useState(storage.get(key) ?? initValue); diff --git a/x-pack/plugins/aiops/public/hooks/use_time_filter.ts b/x-pack/plugins/aiops/public/hooks/use_time_filter.ts index 1dcdf3a2539b63..4f2a33966f71e5 100644 --- a/x-pack/plugins/aiops/public/hooks/use_time_filter.ts +++ b/x-pack/plugins/aiops/public/hooks/use_time_filter.ts @@ -6,7 +6,7 @@ */ import { useEffect } from 'react'; -import { useAiOpsKibana } from '../kibana_context'; +import { useAiopsAppContext } from './use_aiops_app_context'; interface UseTimefilterOptions { timeRangeSelector?: boolean; @@ -17,8 +17,13 @@ export const useTimefilter = ({ timeRangeSelector, autoRefreshSelector, }: UseTimefilterOptions = {}) => { - const { services } = useAiOpsKibana(); - const { timefilter } = services.data.query.timefilter; + const { + data: { + query: { + timefilter: { timefilter }, + }, + }, + } = useAiopsAppContext(); useEffect(() => { if (timeRangeSelector === true && !timefilter.isTimeRangeSelectorEnabled()) { diff --git a/x-pack/plugins/aiops/public/hooks/url_state.ts b/x-pack/plugins/aiops/public/hooks/use_url_state.ts similarity index 99% rename from x-pack/plugins/aiops/public/hooks/url_state.ts rename to x-pack/plugins/aiops/public/hooks/use_url_state.ts index 97699f3a8f2eb4..21d58c5766c526 100644 --- a/x-pack/plugins/aiops/public/hooks/url_state.ts +++ b/x-pack/plugins/aiops/public/hooks/use_url_state.ts @@ -13,7 +13,7 @@ export interface Dictionary { [id: string]: TValue; } -// duplicate of ml/object_utils +// TODO duplicate of ml/object_utils export const getNestedProperty = ( obj: Record, accessor: string, diff --git a/x-pack/plugins/aiops/public/index.ts b/x-pack/plugins/aiops/public/index.ts index 5810d38d573084..1f8373839493ee 100755 --- a/x-pack/plugins/aiops/public/index.ts +++ b/x-pack/plugins/aiops/public/index.ts @@ -14,4 +14,3 @@ export function plugin() { } export { ExplainLogRateSpikes } from './shared_lazy_components'; -export type { AiopsPluginSetup, AiopsPluginStart } from './types'; diff --git a/x-pack/plugins/aiops/public/kibana_context.ts b/x-pack/plugins/aiops/public/kibana_context.ts deleted file mode 100644 index feb0c4ce16c621..00000000000000 --- a/x-pack/plugins/aiops/public/kibana_context.ts +++ /dev/null @@ -1,18 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { CoreStart } from '@kbn/core/public'; -import { KibanaReactContextValue, useKibana } from '@kbn/kibana-react-plugin/public'; -import type { IStorageWrapper } from '@kbn/kibana-utils-plugin/public'; -import type { AiOpsStartDependencies } from './plugin'; - -export type StartServices = CoreStart & - AiOpsStartDependencies & { - storage: IStorageWrapper; - }; -export type AiOpsKibanaReactContextValue = KibanaReactContextValue; -export const useAiOpsKibana = () => useKibana(); diff --git a/x-pack/plugins/aiops/public/kibana_services.ts b/x-pack/plugins/aiops/public/kibana_services.ts deleted file mode 100644 index 2219dfa4677a9b..00000000000000 --- a/x-pack/plugins/aiops/public/kibana_services.ts +++ /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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { CoreStart } from '@kbn/core/public'; -import { AiOpsStartDependencies } from './plugin'; - -let coreStart: CoreStart; -let pluginsStart: AiOpsStartDependencies; -export function setStartServices(core: CoreStart, plugins: AiOpsStartDependencies) { - coreStart = core; - pluginsStart = plugins; -} - -export const getCoreStart = () => coreStart; -export const getPluginsStart = () => pluginsStart; diff --git a/x-pack/plugins/aiops/public/plugin.ts b/x-pack/plugins/aiops/public/plugin.ts index c6126ec2db7a9a..0232473a40f113 100755 --- a/x-pack/plugins/aiops/public/plugin.ts +++ b/x-pack/plugins/aiops/public/plugin.ts @@ -5,28 +5,10 @@ * 2.0. */ -import { CoreSetup, CoreStart, Plugin } from '@kbn/core/public'; -import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; -import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public'; -import { ChartsPluginStart } from '@kbn/charts-plugin/public'; -import { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; -import type { SharePluginStart } from '@kbn/share-plugin/public'; +import { Plugin } from '@kbn/core/public'; -import { AiopsPluginSetup, AiopsPluginStart } from './types'; -import { setStartServices } from './kibana_services'; - -export interface AiOpsStartDependencies { - data: DataPublicPluginStart; - charts: ChartsPluginStart; - fieldFormats: FieldFormatsStart; - unifiedSearch: UnifiedSearchPublicPluginStart; - share: SharePluginStart; -} - -export class AiopsPlugin implements Plugin { - public setup(core: CoreSetup) {} - public start(core: CoreStart, plugins: AiOpsStartDependencies) { - setStartServices(core, plugins); - } +export class AiopsPlugin implements Plugin { + public setup() {} + public start() {} public stop() {} } diff --git a/x-pack/plugins/aiops/public/types.ts b/x-pack/plugins/aiops/public/types.ts deleted file mode 100755 index 453142258be2d1..00000000000000 --- a/x-pack/plugins/aiops/public/types.ts +++ /dev/null @@ -1,21 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { AiopsPlugin } from './plugin'; - -/** - * aiops plugin public setup contract - */ -export type AiopsPluginSetup = ReturnType; - -/** - * aiops plugin public start contract - */ -export type AiopsPluginStart = ReturnType; - -// eslint-disable-next-line @typescript-eslint/consistent-type-definitions -export type AppPluginStartDependencies = {}; diff --git a/x-pack/plugins/alerting/common/execution_log_types.ts b/x-pack/plugins/alerting/common/execution_log_types.ts index 74f2d7a000e27c..41406bb6c9dc1e 100644 --- a/x-pack/plugins/alerting/common/execution_log_types.ts +++ b/x-pack/plugins/alerting/common/execution_log_types.ts @@ -48,6 +48,7 @@ export interface IExecutionLog { es_search_duration_ms: number; schedule_delay_ms: number; timed_out: boolean; + rule_id: string; } export interface IExecutionErrors { diff --git a/x-pack/plugins/alerting/server/lib/get_execution_log_aggregation.test.ts b/x-pack/plugins/alerting/server/lib/get_execution_log_aggregation.test.ts index c9f127a63d8c52..bd3fc05c6d8f75 100644 --- a/x-pack/plugins/alerting/server/lib/get_execution_log_aggregation.test.ts +++ b/x-pack/plugins/alerting/server/lib/get_execution_log_aggregation.test.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { fromKueryExpression } from '@kbn/es-query'; import { getNumExecutions, getExecutionLogAggregation, @@ -271,7 +272,421 @@ describe('getExecutionLogAggregation', () => { top_hits: { size: 1, _source: { - includes: ['event.outcome', 'message', 'error.message', 'kibana.version'], + includes: [ + 'event.outcome', + 'message', + 'error.message', + 'kibana.version', + 'rule.id', + ], + }, + }, + }, + }, + }, + timeoutMessage: { + filter: { + bool: { + must: [ + { match: { 'event.action': 'execute-timeout' } }, + { match: { 'event.provider': 'alerting' } }, + ], + }, + }, + }, + }, + }, + }, + }, + }); + }); + + test('should correctly generate aggregation with a defined filter in the form of a string', () => { + expect( + getExecutionLogAggregation({ + page: 2, + perPage: 10, + sort: [{ timestamp: { order: 'asc' } }, { execution_duration: { order: 'desc' } }], + filter: 'test:test', + }) + ).toEqual({ + excludeExecuteStart: { + filter: { + bool: { + must_not: [ + { + term: { + 'event.action': 'execute-start', + }, + }, + ], + }, + }, + aggs: { + executionUuidCardinality: { + aggs: { + executionUuidCardinality: { + cardinality: { field: 'kibana.alert.rule.execution.uuid' }, + }, + }, + filter: { + bool: { + filter: { + bool: { + minimum_should_match: 1, + should: [ + { + match: { + test: 'test', + }, + }, + ], + }, + }, + must: [ + { + bool: { + must: [ + { + match: { + 'event.action': 'execute', + }, + }, + { + match: { + 'event.provider': 'alerting', + }, + }, + ], + }, + }, + ], + }, + }, + }, + executionUuid: { + terms: { + field: 'kibana.alert.rule.execution.uuid', + size: 1000, + order: [ + { 'ruleExecution>executeStartTime': 'asc' }, + { 'ruleExecution>executionDuration': 'desc' }, + ], + }, + aggs: { + executionUuidSorted: { + bucket_sort: { + sort: [ + { 'ruleExecution>executeStartTime': { order: 'asc' } }, + { 'ruleExecution>executionDuration': { order: 'desc' } }, + ], + from: 10, + size: 10, + gap_policy: 'insert_zeros', + }, + }, + actionExecution: { + filter: { + bool: { + must: [ + { match: { 'event.action': 'execute' } }, + { match: { 'event.provider': 'actions' } }, + ], + }, + }, + aggs: { actionOutcomes: { terms: { field: 'event.outcome', size: 2 } } }, + }, + minExecutionUuidBucket: { + bucket_selector: { + buckets_path: { + count: 'ruleExecution._count', + }, + script: { + source: 'params.count > 0', + }, + }, + }, + ruleExecution: { + filter: { + bool: { + filter: { + bool: { + minimum_should_match: 1, + should: [ + { + match: { + test: 'test', + }, + }, + ], + }, + }, + must: [ + { + bool: { + must: [ + { match: { 'event.action': 'execute' } }, + { match: { 'event.provider': 'alerting' } }, + ], + }, + }, + ], + }, + }, + aggs: { + executeStartTime: { min: { field: 'event.start' } }, + scheduleDelay: { + max: { + field: 'kibana.task.schedule_delay', + }, + }, + totalSearchDuration: { + max: { field: 'kibana.alert.rule.execution.metrics.total_search_duration_ms' }, + }, + esSearchDuration: { + max: { field: 'kibana.alert.rule.execution.metrics.es_search_duration_ms' }, + }, + numTriggeredActions: { + max: { + field: 'kibana.alert.rule.execution.metrics.number_of_triggered_actions', + }, + }, + numGeneratedActions: { + max: { + field: 'kibana.alert.rule.execution.metrics.number_of_generated_actions', + }, + }, + numActiveAlerts: { + max: { + field: 'kibana.alert.rule.execution.metrics.alert_counts.active', + }, + }, + numRecoveredAlerts: { + max: { + field: 'kibana.alert.rule.execution.metrics.alert_counts.recovered', + }, + }, + numNewAlerts: { + max: { + field: 'kibana.alert.rule.execution.metrics.alert_counts.new', + }, + }, + executionDuration: { max: { field: 'event.duration' } }, + outcomeAndMessage: { + top_hits: { + size: 1, + _source: { + includes: [ + 'event.outcome', + 'message', + 'error.message', + 'kibana.version', + 'rule.id', + ], + }, + }, + }, + }, + }, + timeoutMessage: { + filter: { + bool: { + must: [ + { match: { 'event.action': 'execute-timeout' } }, + { match: { 'event.provider': 'alerting' } }, + ], + }, + }, + }, + }, + }, + }, + }, + }); + }); + + test('should correctly generate aggregation with a defined filter in the form of a KueryNode', () => { + expect( + getExecutionLogAggregation({ + page: 2, + perPage: 10, + sort: [{ timestamp: { order: 'asc' } }, { execution_duration: { order: 'desc' } }], + filter: fromKueryExpression('test:test'), + }) + ).toEqual({ + excludeExecuteStart: { + filter: { + bool: { + must_not: [ + { + term: { + 'event.action': 'execute-start', + }, + }, + ], + }, + }, + aggs: { + executionUuidCardinality: { + aggs: { + executionUuidCardinality: { + cardinality: { field: 'kibana.alert.rule.execution.uuid' }, + }, + }, + filter: { + bool: { + filter: { + bool: { + minimum_should_match: 1, + should: [ + { + match: { + test: 'test', + }, + }, + ], + }, + }, + must: [ + { + bool: { + must: [ + { + match: { + 'event.action': 'execute', + }, + }, + { + match: { + 'event.provider': 'alerting', + }, + }, + ], + }, + }, + ], + }, + }, + }, + executionUuid: { + terms: { + field: 'kibana.alert.rule.execution.uuid', + size: 1000, + order: [ + { 'ruleExecution>executeStartTime': 'asc' }, + { 'ruleExecution>executionDuration': 'desc' }, + ], + }, + aggs: { + executionUuidSorted: { + bucket_sort: { + sort: [ + { 'ruleExecution>executeStartTime': { order: 'asc' } }, + { 'ruleExecution>executionDuration': { order: 'desc' } }, + ], + from: 10, + size: 10, + gap_policy: 'insert_zeros', + }, + }, + actionExecution: { + filter: { + bool: { + must: [ + { match: { 'event.action': 'execute' } }, + { match: { 'event.provider': 'actions' } }, + ], + }, + }, + aggs: { actionOutcomes: { terms: { field: 'event.outcome', size: 2 } } }, + }, + minExecutionUuidBucket: { + bucket_selector: { + buckets_path: { + count: 'ruleExecution._count', + }, + script: { + source: 'params.count > 0', + }, + }, + }, + ruleExecution: { + filter: { + bool: { + filter: { + bool: { + minimum_should_match: 1, + should: [ + { + match: { + test: 'test', + }, + }, + ], + }, + }, + must: [ + { + bool: { + must: [ + { match: { 'event.action': 'execute' } }, + { match: { 'event.provider': 'alerting' } }, + ], + }, + }, + ], + }, + }, + aggs: { + executeStartTime: { min: { field: 'event.start' } }, + scheduleDelay: { + max: { + field: 'kibana.task.schedule_delay', + }, + }, + totalSearchDuration: { + max: { field: 'kibana.alert.rule.execution.metrics.total_search_duration_ms' }, + }, + esSearchDuration: { + max: { field: 'kibana.alert.rule.execution.metrics.es_search_duration_ms' }, + }, + numTriggeredActions: { + max: { + field: 'kibana.alert.rule.execution.metrics.number_of_triggered_actions', + }, + }, + numGeneratedActions: { + max: { + field: 'kibana.alert.rule.execution.metrics.number_of_generated_actions', + }, + }, + numActiveAlerts: { + max: { + field: 'kibana.alert.rule.execution.metrics.alert_counts.active', + }, + }, + numRecoveredAlerts: { + max: { + field: 'kibana.alert.rule.execution.metrics.alert_counts.recovered', + }, + }, + numNewAlerts: { + max: { + field: 'kibana.alert.rule.execution.metrics.alert_counts.new', + }, + }, + executionDuration: { max: { field: 'event.duration' } }, + outcomeAndMessage: { + top_hits: { + size: 1, + _source: { + includes: [ + 'event.outcome', + 'message', + 'error.message', + 'kibana.version', + 'rule.id', + ], }, }, }, @@ -361,6 +776,7 @@ describe('formatExecutionLogResult', () => { _id: 'S4wIZX8B8TGQpG7XQZns', _score: 1.0, _source: { + rule: { id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef' }, event: { outcome: 'success', }, @@ -444,6 +860,8 @@ describe('formatExecutionLogResult', () => { _id: 'a4wIZX8B8TGQpG7Xwpnz', _score: 1.0, _source: { + rule: { id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef' }, + event: { outcome: 'success', }, @@ -521,6 +939,7 @@ describe('formatExecutionLogResult', () => { es_search_duration_ms: 0, timed_out: false, schedule_delay_ms: 3074, + rule_id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef', }, { id: '41b2755e-765a-4044-9745-b03875d5e79a', @@ -541,6 +960,7 @@ describe('formatExecutionLogResult', () => { es_search_duration_ms: 0, timed_out: false, schedule_delay_ms: 3126, + rule_id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef', }, ], }); @@ -595,6 +1015,7 @@ describe('formatExecutionLogResult', () => { _id: 'S4wIZX8B8TGQpG7XQZns', _score: 1.0, _source: { + rule: { id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef' }, event: { outcome: 'failure', }, @@ -681,6 +1102,7 @@ describe('formatExecutionLogResult', () => { _id: 'a4wIZX8B8TGQpG7Xwpnz', _score: 1.0, _source: { + rule: { id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef' }, event: { outcome: 'success', }, @@ -758,6 +1180,7 @@ describe('formatExecutionLogResult', () => { es_search_duration_ms: 0, timed_out: false, schedule_delay_ms: 3074, + rule_id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef', }, { id: '41b2755e-765a-4044-9745-b03875d5e79a', @@ -778,6 +1201,7 @@ describe('formatExecutionLogResult', () => { es_search_duration_ms: 0, timed_out: false, schedule_delay_ms: 3126, + rule_id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef', }, ], }); @@ -832,6 +1256,7 @@ describe('formatExecutionLogResult', () => { _id: 'dJkWa38B1ylB1EvsAckB', _score: 1.0, _source: { + rule: { id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef' }, event: { outcome: 'success', }, @@ -910,6 +1335,7 @@ describe('formatExecutionLogResult', () => { _id: 'a4wIZX8B8TGQpG7Xwpnz', _score: 1.0, _source: { + rule: { id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef' }, event: { outcome: 'success', }, @@ -987,6 +1413,7 @@ describe('formatExecutionLogResult', () => { es_search_duration_ms: 0, timed_out: true, schedule_delay_ms: 3074, + rule_id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef', }, { id: '41b2755e-765a-4044-9745-b03875d5e79a', @@ -1007,6 +1434,7 @@ describe('formatExecutionLogResult', () => { es_search_duration_ms: 0, timed_out: false, schedule_delay_ms: 3126, + rule_id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef', }, ], }); @@ -1061,6 +1489,7 @@ describe('formatExecutionLogResult', () => { _id: '7xKcb38BcntAq5ycFwiu', _score: 1.0, _source: { + rule: { id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef' }, event: { outcome: 'success', }, @@ -1144,6 +1573,7 @@ describe('formatExecutionLogResult', () => { _id: 'zRKbb38BcntAq5ycOwgk', _score: 1.0, _source: { + rule: { id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef' }, event: { outcome: 'success', }, @@ -1221,6 +1651,7 @@ describe('formatExecutionLogResult', () => { es_search_duration_ms: 0, timed_out: false, schedule_delay_ms: 3126, + rule_id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef', }, { id: '61bb867b-661a-471f-bf92-23471afa10b3', @@ -1241,6 +1672,7 @@ describe('formatExecutionLogResult', () => { es_search_duration_ms: 0, timed_out: false, schedule_delay_ms: 3133, + rule_id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef', }, ], }); diff --git a/x-pack/plugins/alerting/server/lib/get_execution_log_aggregation.ts b/x-pack/plugins/alerting/server/lib/get_execution_log_aggregation.ts index 7365c9d125d00d..14d67807a86af4 100644 --- a/x-pack/plugins/alerting/server/lib/get_execution_log_aggregation.ts +++ b/x-pack/plugins/alerting/server/lib/get_execution_log_aggregation.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { KueryNode } from '@kbn/core-saved-objects-api-server'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import Boom from '@hapi/boom'; import { flatMap, get } from 'lodash'; @@ -15,6 +16,7 @@ import { IExecutionLog, IExecutionLogResult } from '../../common'; const DEFAULT_MAX_BUCKETS_LIMIT = 1000; // do not retrieve more than this number of executions +const RULE_ID_FIELD = 'rule.id'; const PROVIDER_FIELD = 'event.provider'; const START_FIELD = 'event.start'; const ACTION_FIELD = 'event.action'; @@ -80,7 +82,7 @@ interface ExcludeExecuteStartAggResult extends estypes.AggregationsAggregateBase }; } export interface IExecutionLogAggOptions { - filter?: string; + filter?: string | KueryNode; page: number; perPage: number; sort: estypes.Sort; @@ -129,7 +131,8 @@ export function getExecutionLogAggregation({ let dslFilterQuery: estypes.QueryDslBoolQuery['filter']; try { - dslFilterQuery = filter ? toElasticsearchQuery(fromKueryExpression(filter)) : undefined; + const filterKueryNode = typeof filter === 'string' ? fromKueryExpression(filter) : filter; + dslFilterQuery = filter ? toElasticsearchQuery(filterKueryNode) : undefined; } catch (err) { throw Boom.badRequest(`Invalid kuery syntax for filter ${filter}`); } @@ -256,7 +259,13 @@ export function getExecutionLogAggregation({ top_hits: { size: 1, _source: { - includes: [OUTCOME_FIELD, MESSAGE_FIELD, ERROR_MESSAGE_FIELD, VERSION_FIELD], + includes: [ + OUTCOME_FIELD, + MESSAGE_FIELD, + ERROR_MESSAGE_FIELD, + VERSION_FIELD, + RULE_ID_FIELD, + ], }, }, }, @@ -325,6 +334,8 @@ function formatExecutionLogAggBucket(bucket: IExecutionUuidAggBucket): IExecutio ? `${outcomeAndMessage?.message ?? ''} - ${outcomeAndMessage?.error?.message ?? ''}` : outcomeAndMessage?.message ?? ''; const version = outcomeAndMessage ? outcomeAndMessage?.kibana?.version ?? '' : ''; + + const ruleId = outcomeAndMessage ? outcomeAndMessage?.rule?.id ?? '' : ''; return { id: bucket?.key ?? '', timestamp: bucket?.ruleExecution?.executeStartTime.value_as_string ?? '', @@ -343,6 +354,7 @@ function formatExecutionLogAggBucket(bucket: IExecutionUuidAggBucket): IExecutio es_search_duration_ms: bucket?.ruleExecution?.esSearchDuration?.value ?? 0, schedule_delay_ms: scheduleDelayUs / Millis2Nanos, timed_out: timedOut, + rule_id: ruleId, }; } diff --git a/x-pack/plugins/alerting/server/routes/get_global_execution_logs.test.ts b/x-pack/plugins/alerting/server/routes/get_global_execution_logs.test.ts new file mode 100644 index 00000000000000..4c7f6c0a2750e0 --- /dev/null +++ b/x-pack/plugins/alerting/server/routes/get_global_execution_logs.test.ts @@ -0,0 +1,113 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { getGlobalExecutionLogRoute } from './get_global_execution_logs'; +import { httpServiceMock } from '@kbn/core/server/mocks'; +import { licenseStateMock } from '../lib/license_state.mock'; +import { mockHandlerArguments } from './_mock_handler_arguments'; +import { rulesClientMock } from '../rules_client.mock'; +import { IExecutionLogResult } from '../../common'; + +const rulesClient = rulesClientMock.create(); +jest.mock('../lib/license_api_access', () => ({ + verifyApiAccess: jest.fn(), +})); + +beforeEach(() => { + jest.resetAllMocks(); +}); + +describe('getRuleExecutionLogRoute', () => { + const dateString = new Date().toISOString(); + const mockedExecutionLog: IExecutionLogResult = { + total: 374, + data: [ + { + id: '6705da7d-2635-499d-a6a8-1aee1ae1eac9', + timestamp: '2022-03-07T15:38:32.617Z', + duration_ms: 1056, + status: 'success', + message: + "rule executed: example.always-firing:a348a740-9e2c-11ec-bd64-774ed95c43ef: 'test rule'", + version: '8.2.0', + num_active_alerts: 5, + num_new_alerts: 5, + num_recovered_alerts: 0, + num_triggered_actions: 5, + num_generated_actions: 5, + num_succeeded_actions: 5, + num_errored_actions: 0, + total_search_duration_ms: 0, + es_search_duration_ms: 0, + timed_out: false, + schedule_delay_ms: 3126, + rule_id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef', + }, + { + id: '41b2755e-765a-4044-9745-b03875d5e79a', + timestamp: '2022-03-07T15:39:05.604Z', + duration_ms: 1165, + status: 'success', + message: + "rule executed: example.always-firing:a348a740-9e2c-11ec-bd64-774ed95c43ef: 'test rule'", + version: '8.2.0', + num_active_alerts: 5, + num_new_alerts: 5, + num_recovered_alerts: 5, + num_triggered_actions: 5, + num_generated_actions: 5, + num_succeeded_actions: 5, + num_errored_actions: 0, + total_search_duration_ms: 0, + es_search_duration_ms: 0, + timed_out: false, + schedule_delay_ms: 3008, + rule_id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef', + }, + ], + }; + + it('gets global execution logs', async () => { + const licenseState = licenseStateMock.create(); + const router = httpServiceMock.createRouter(); + + getGlobalExecutionLogRoute(router, licenseState); + + const [config, handler] = router.get.mock.calls[0]; + + expect(config.path).toMatchInlineSnapshot(`"/internal/alerting/_global_execution_logs"`); + + rulesClient.getGlobalExecutionLogWithAuth.mockResolvedValue(mockedExecutionLog); + + const [context, req, res] = mockHandlerArguments( + { rulesClient }, + { + query: { + date_start: dateString, + per_page: 10, + page: 1, + sort: [{ timestamp: { order: 'desc' } }], + }, + }, + ['ok'] + ); + + await handler(context, req, res); + + expect(rulesClient.getGlobalExecutionLogWithAuth).toHaveBeenCalledTimes(1); + expect(rulesClient.getGlobalExecutionLogWithAuth.mock.calls[0]).toEqual([ + { + dateStart: dateString, + page: 1, + perPage: 10, + sort: [{ timestamp: { order: 'desc' } }], + }, + ]); + + expect(res.ok).toHaveBeenCalled(); + }); +}); diff --git a/x-pack/plugins/alerting/server/routes/get_global_execution_logs.ts b/x-pack/plugins/alerting/server/routes/get_global_execution_logs.ts new file mode 100644 index 00000000000000..4695e5e7bdf891 --- /dev/null +++ b/x-pack/plugins/alerting/server/routes/get_global_execution_logs.ts @@ -0,0 +1,75 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { IRouter } from '@kbn/core/server'; +import { schema } from '@kbn/config-schema'; +import { ILicenseState } from '../lib'; +import { GetGlobalExecutionLogParams } from '../rules_client'; +import { RewriteRequestCase, verifyAccessAndContext } from './lib'; +import { AlertingRequestHandlerContext, INTERNAL_BASE_ALERTING_API_PATH } from '../types'; + +const sortOrderSchema = schema.oneOf([schema.literal('asc'), schema.literal('desc')]); + +const sortFieldSchema = schema.oneOf([ + schema.object({ timestamp: schema.object({ order: sortOrderSchema }) }), + schema.object({ execution_duration: schema.object({ order: sortOrderSchema }) }), + schema.object({ total_search_duration: schema.object({ order: sortOrderSchema }) }), + schema.object({ es_search_duration: schema.object({ order: sortOrderSchema }) }), + schema.object({ schedule_delay: schema.object({ order: sortOrderSchema }) }), + schema.object({ num_triggered_actions: schema.object({ order: sortOrderSchema }) }), + schema.object({ num_generated_actions: schema.object({ order: sortOrderSchema }) }), + schema.object({ num_active_alerts: schema.object({ order: sortOrderSchema }) }), + schema.object({ num_recovered_alerts: schema.object({ order: sortOrderSchema }) }), + schema.object({ num_new_alerts: schema.object({ order: sortOrderSchema }) }), +]); + +const sortFieldsSchema = schema.arrayOf(sortFieldSchema, { + defaultValue: [{ timestamp: { order: 'desc' } }], +}); + +const querySchema = schema.object({ + date_start: schema.string(), + date_end: schema.maybe(schema.string()), + filter: schema.maybe(schema.string()), + per_page: schema.number({ defaultValue: 10, min: 1 }), + page: schema.number({ defaultValue: 1, min: 1 }), + sort: sortFieldsSchema, +}); + +const rewriteReq: RewriteRequestCase = ({ + date_start: dateStart, + date_end: dateEnd, + per_page: perPage, + ...rest +}) => ({ + ...rest, + dateStart, + dateEnd, + perPage, +}); + +export const getGlobalExecutionLogRoute = ( + router: IRouter, + licenseState: ILicenseState +) => { + router.get( + { + path: `${INTERNAL_BASE_ALERTING_API_PATH}/_global_execution_logs`, + validate: { + query: querySchema, + }, + }, + router.handleLegacyErrors( + verifyAccessAndContext(licenseState, async function (context, req, res) { + const rulesClient = (await context.alerting).getRulesClient(); + return res.ok({ + body: await rulesClient.getGlobalExecutionLogWithAuth(rewriteReq(req.query)), + }); + }) + ) + ); +}; diff --git a/x-pack/plugins/alerting/server/routes/get_rule_execution_log.test.ts b/x-pack/plugins/alerting/server/routes/get_rule_execution_log.test.ts index 5271cd73736977..9c1be8628c8234 100644 --- a/x-pack/plugins/alerting/server/routes/get_rule_execution_log.test.ts +++ b/x-pack/plugins/alerting/server/routes/get_rule_execution_log.test.ts @@ -46,6 +46,7 @@ describe('getRuleExecutionLogRoute', () => { es_search_duration_ms: 0, timed_out: false, schedule_delay_ms: 3126, + rule_id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef', }, { id: '41b2755e-765a-4044-9745-b03875d5e79a', @@ -66,6 +67,7 @@ describe('getRuleExecutionLogRoute', () => { es_search_duration_ms: 0, timed_out: false, schedule_delay_ms: 3008, + rule_id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef', }, ], }; diff --git a/x-pack/plugins/alerting/server/routes/index.ts b/x-pack/plugins/alerting/server/routes/index.ts index ef837a83ad9a49..7d524a190122a1 100644 --- a/x-pack/plugins/alerting/server/routes/index.ts +++ b/x-pack/plugins/alerting/server/routes/index.ts @@ -21,6 +21,7 @@ import { enableRuleRoute } from './enable_rule'; import { findRulesRoute, findInternalRulesRoute } from './find_rules'; import { getRuleAlertSummaryRoute } from './get_rule_alert_summary'; import { getRuleExecutionLogRoute } from './get_rule_execution_log'; +import { getGlobalExecutionLogRoute } from './get_global_execution_logs'; import { getActionErrorLogRoute } from './get_action_error_log'; import { getRuleStateRoute } from './get_rule_state'; import { healthRoute } from './health'; @@ -59,6 +60,7 @@ export function defineRoutes(opts: RouteOptions) { findInternalRulesRoute(router, licenseState, usageCounter); getRuleAlertSummaryRoute(router, licenseState); getRuleExecutionLogRoute(router, licenseState); + getGlobalExecutionLogRoute(router, licenseState); getActionErrorLogRoute(router, licenseState); getRuleStateRoute(router, licenseState); healthRoute(router, licenseState, encryptedSavedObjects); diff --git a/x-pack/plugins/alerting/server/rules_client.mock.ts b/x-pack/plugins/alerting/server/rules_client.mock.ts index 394f43ab389e47..9ecbc21ccb0850 100644 --- a/x-pack/plugins/alerting/server/rules_client.mock.ts +++ b/x-pack/plugins/alerting/server/rules_client.mock.ts @@ -30,6 +30,7 @@ const createRulesClientMock = () => { listAlertTypes: jest.fn(), getAlertSummary: jest.fn(), getExecutionLogForRule: jest.fn(), + getGlobalExecutionLogWithAuth: jest.fn(), getActionErrorLog: jest.fn(), getSpaceId: jest.fn(), bulkEdit: jest.fn(), diff --git a/x-pack/plugins/alerting/server/rules_client/audit_events.ts b/x-pack/plugins/alerting/server/rules_client/audit_events.ts index 215e16f32f29af..c830330a77ca22 100644 --- a/x-pack/plugins/alerting/server/rules_client/audit_events.ts +++ b/x-pack/plugins/alerting/server/rules_client/audit_events.ts @@ -25,6 +25,7 @@ export enum RuleAuditAction { AGGREGATE = 'rule_aggregate', BULK_EDIT = 'rule_bulk_edit', GET_EXECUTION_LOG = 'rule_get_execution_log', + GET_GLOBAL_EXECUTION_LOG = 'rule_get_global_execution_log', GET_ACTION_ERROR_LOG = 'rule_get_action_error_log', SNOOZE = 'rule_snooze', UNSNOOZE = 'rule_unsnooze', @@ -53,6 +54,11 @@ const eventVerbs: Record = { 'accessing execution log for', 'accessed execution log for', ], + rule_get_global_execution_log: [ + 'access execution log', + 'accessing execution log', + 'accessed execution log', + ], rule_get_action_error_log: [ 'access action error log for', 'accessing action error log for', @@ -79,6 +85,7 @@ const eventTypes: Record = { rule_alert_unmute: 'change', rule_aggregate: 'access', rule_get_execution_log: 'access', + rule_get_global_execution_log: 'access', rule_get_action_error_log: 'access', rule_snooze: 'change', rule_unsnooze: 'change', diff --git a/x-pack/plugins/alerting/server/rules_client/rules_client.ts b/x-pack/plugins/alerting/server/rules_client/rules_client.ts index 35462f9cc4e753..f0cf88615047dc 100644 --- a/x-pack/plugins/alerting/server/rules_client/rules_client.ts +++ b/x-pack/plugins/alerting/server/rules_client/rules_client.ts @@ -365,6 +365,15 @@ export interface GetExecutionLogByIdParams { sort: estypes.Sort; } +export interface GetGlobalExecutionLogParams { + dateStart: string; + dateEnd?: string; + filter?: string; + page: number; + perPage: number; + sort: estypes.Sort; +} + export interface GetActionErrorLogByIdParams { id: string; dateStart: string; @@ -875,6 +884,100 @@ export class RulesClient { } } + public async getGlobalExecutionLogWithAuth({ + dateStart, + dateEnd, + filter, + page, + perPage, + sort, + }: GetGlobalExecutionLogParams): Promise { + this.logger.debug(`getGlobalExecutionLogWithAuth(): getting global execution log`); + + let authorizationTuple; + try { + authorizationTuple = await this.authorization.getFindAuthorizationFilter( + AlertingAuthorizationEntity.Alert, + { + type: AlertingAuthorizationFilterType.KQL, + fieldNames: { + ruleTypeId: 'kibana.alert.rule.rule_type_id', + consumer: 'kibana.alert.rule.consumer', + }, + } + ); + } catch (error) { + this.auditLogger?.log( + ruleAuditEvent({ + action: RuleAuditAction.GET_GLOBAL_EXECUTION_LOG, + error, + }) + ); + throw error; + } + + this.auditLogger?.log( + ruleAuditEvent({ + action: RuleAuditAction.GET_GLOBAL_EXECUTION_LOG, + }) + ); + + const dateNow = new Date(); + const parsedDateStart = parseDate(dateStart, 'dateStart', dateNow); + const parsedDateEnd = parseDate(dateEnd, 'dateEnd', dateNow); + + const eventLogClient = await this.getEventLogClient(); + + try { + const aggResult = await eventLogClient.aggregateEventsWithAuthFilter( + 'alert', + authorizationTuple.filter as KueryNode, + { + start: parsedDateStart.toISOString(), + end: parsedDateEnd.toISOString(), + aggs: getExecutionLogAggregation({ + filter, + page, + perPage, + sort, + }), + } + ); + + const formattedResult = formatExecutionLogResult(aggResult); + const ruleIds = [...new Set(formattedResult.data.map((l) => l.rule_id))].filter( + Boolean + ) as string[]; + const ruleNameIdEntries = await Promise.all( + ruleIds.map(async (id) => { + try { + const result = await this.get({ id }); + return [id, result.name]; + } catch (e) { + return [id, id]; + } + }) + ); + const ruleNameIdMap: Record = ruleNameIdEntries.reduce( + (result, [key, val]) => ({ ...result, [key]: val }), + {} + ); + + return { + ...formattedResult, + data: formattedResult.data.map((entry) => ({ + ...entry, + rule_name: ruleNameIdMap[entry.rule_id!], + })), + }; + } catch (err) { + this.logger.debug( + `rulesClient.getGlobalExecutionLogWithAuth(): error searching global event log: ${err.message}` + ); + throw err; + } + } + public async getActionErrorLog({ id, dateStart, diff --git a/x-pack/plugins/alerting/server/rules_client/tests/get_execution_log.test.ts b/x-pack/plugins/alerting/server/rules_client/tests/get_execution_log.test.ts index 5cdf4c77442200..cf525f59e9448c 100644 --- a/x-pack/plugins/alerting/server/rules_client/tests/get_execution_log.test.ts +++ b/x-pack/plugins/alerting/server/rules_client/tests/get_execution_log.test.ts @@ -21,6 +21,7 @@ import { RawRule } from '../../types'; import { auditLoggerMock } from '@kbn/security-plugin/server/audit/mocks'; import { getBeforeSetup, mockedDateString, setGlobalDate } from './lib'; import { getExecutionLogAggregation } from '../../lib/get_execution_log_aggregation'; +import { fromKueryExpression } from '@kbn/es-query'; const taskManager = taskManagerMock.createStart(); const ruleTypeRegistry = ruleTypeRegistryMock.create(); @@ -142,6 +143,9 @@ const aggregateResults = { _id: 'S4wIZX8B8TGQpG7XQZns', _score: 1.0, _source: { + rule: { + id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef', + }, event: { outcome: 'success', }, @@ -171,6 +175,25 @@ const aggregateResults = { value: 1.646667512617e12, value_as_string: '2022-03-07T15:38:32.617Z', }, + ruleId: { + hits: { + total: { + value: 1, + relation: 'eq', + }, + max_score: 1.0, + hits: [ + { + _index: '.kibana-event-log-8.2.0-000001', + _id: 'S4wIZX8B8TGQpG7XQZns', + _score: 1.0, + _source: { + rule: { id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef' }, + }, + }, + ], + }, + }, }, actionExecution: { meta: {}, @@ -225,6 +248,7 @@ const aggregateResults = { _id: 'a4wIZX8B8TGQpG7Xwpnz', _score: 1.0, _source: { + rule: { id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef' }, event: { outcome: 'success', }, @@ -254,6 +278,25 @@ const aggregateResults = { value: 1.646667545604e12, value_as_string: '2022-03-07T15:39:05.604Z', }, + ruleId: { + hits: { + total: { + value: 1, + relation: 'eq', + }, + max_score: 1.0, + hits: [ + { + _index: '.kibana-event-log-8.2.0-000001', + _id: 'S4wIZX8B8TGQpG7XQZns', + _score: 1.0, + _source: { + rule: { id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef' }, + }, + }, + ], + }, + }, }, actionExecution: { meta: {}, @@ -333,6 +376,7 @@ describe('getExecutionLogForRule()', () => { es_search_duration_ms: 0, timed_out: false, schedule_delay_ms: 3126, + rule_id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef', }, { id: '41b2755e-765a-4044-9745-b03875d5e79a', @@ -353,6 +397,7 @@ describe('getExecutionLogForRule()', () => { es_search_duration_ms: 0, timed_out: false, schedule_delay_ms: 3345, + rule_id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef', }, ], }); @@ -623,3 +668,72 @@ describe('getExecutionLogForRule()', () => { }); }); }); + +describe('getGlobalExecutionLogWithAuth()', () => { + let rulesClient: RulesClient; + + beforeEach(() => { + rulesClient = new RulesClient(rulesClientParams); + }); + + test('runs as expected with some event log aggregation data', async () => { + const ruleSO = getRuleSavedObject({}); + authorization.getFindAuthorizationFilter.mockResolvedValue({ + filter: fromKueryExpression('*'), + ensureRuleTypeIsAuthorized() {}, + }); + unsecuredSavedObjectsClient.get.mockResolvedValueOnce(ruleSO); + eventLogClient.aggregateEventsWithAuthFilter.mockResolvedValueOnce(aggregateResults); + + const result = await rulesClient.getGlobalExecutionLogWithAuth(getExecutionLogByIdParams()); + expect(result).toEqual({ + total: 374, + data: [ + { + id: '6705da7d-2635-499d-a6a8-1aee1ae1eac9', + timestamp: '2022-03-07T15:38:32.617Z', + duration_ms: 1056, + status: 'success', + message: + "rule executed: example.always-firing:a348a740-9e2c-11ec-bd64-774ed95c43ef: 'test rule'", + version: '8.2.0', + num_active_alerts: 5, + num_new_alerts: 5, + num_recovered_alerts: 0, + num_triggered_actions: 5, + num_generated_actions: 5, + num_succeeded_actions: 5, + num_errored_actions: 0, + total_search_duration_ms: 0, + es_search_duration_ms: 0, + timed_out: false, + schedule_delay_ms: 3126, + rule_id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef', + rule_name: 'rule-name', + }, + { + id: '41b2755e-765a-4044-9745-b03875d5e79a', + timestamp: '2022-03-07T15:39:05.604Z', + duration_ms: 1165, + status: 'success', + message: + "rule executed: example.always-firing:a348a740-9e2c-11ec-bd64-774ed95c43ef: 'test rule'", + version: '8.2.0', + num_active_alerts: 5, + num_new_alerts: 5, + num_recovered_alerts: 5, + num_triggered_actions: 5, + num_generated_actions: 5, + num_succeeded_actions: 5, + num_errored_actions: 0, + total_search_duration_ms: 0, + es_search_duration_ms: 0, + timed_out: false, + schedule_delay_ms: 3345, + rule_id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef', + rule_name: 'rule-name', + }, + ], + }); + }); +}); diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/transaction_details/transaction_details.spec.ts b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/transaction_details/transaction_details.spec.ts index ee2aade9ec1dff..5172a5f167fc9e 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/transaction_details/transaction_details.spec.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/transaction_details/transaction_details.spec.ts @@ -55,4 +55,14 @@ describe('Transaction details', () => { .click(); cy.url().should('include', 'opbeans-java/errors'); }); + + describe('when navigating to a trace sample', () => { + it('keeps the same trace sample after reloading the page', () => { + cy.get('[data-test-subj="pagination-button-last"]').click(); + cy.url().then((url) => { + cy.reload(); + cy.url().should('eq', url); + }); + }); + }); }); diff --git a/x-pack/plugins/apm/public/components/app/storage_explorer/index.tsx b/x-pack/plugins/apm/public/components/app/storage_explorer/index.tsx index 4f0c64b226b091..5b8c044d2276c2 100644 --- a/x-pack/plugins/apm/public/components/app/storage_explorer/index.tsx +++ b/x-pack/plugins/apm/public/components/app/storage_explorer/index.tsx @@ -6,22 +6,69 @@ */ import React from 'react'; -import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; +import { + EuiFlexGroup, + EuiFlexItem, + EuiSpacer, + EuiEmptyPrompt, + EuiLoadingSpinner, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import { IndexLifecyclePhaseSelect } from './index_lifecycle_phase_select'; import { ServicesTable } from './services_table'; import { SearchBar } from '../../shared/search_bar'; import { StorageChart } from './storage_chart'; +import { PermissionDenied } from './prompts/permission_denied'; +import { useFetcher, FETCH_STATUS } from '../../../hooks/use_fetcher'; +import { SummaryStats } from './summary_stats'; +import { ApmEnvironmentFilter } from '../../shared/environment_filter'; + +const INITIAL_DATA = { hasPrivileges: false }; export function StorageExplorer() { + const { data: { hasPrivileges } = INITIAL_DATA, status } = useFetcher( + (callApmApi) => { + return callApmApi('GET /internal/apm/storage_explorer/privileges'); + }, + [] + ); + + const loading = status === FETCH_STATUS.LOADING; + + if (loading) { + return ( + } + titleSize="xs" + title={ +

+ {i18n.translate('xpack.apm.storageExplorer.loadingPromptTitle', { + defaultMessage: 'Loading Storage Explorer...', + })} +

+ } + /> + ); + } + + if (!hasPrivileges) { + return ; + } + return ( <> + + + + + diff --git a/x-pack/plugins/apm/public/components/app/storage_explorer/index_lifecycle_phase_select.tsx b/x-pack/plugins/apm/public/components/app/storage_explorer/index_lifecycle_phase_select.tsx index 6a602edc42b56a..124579e0562e28 100644 --- a/x-pack/plugins/apm/public/components/app/storage_explorer/index_lifecycle_phase_select.tsx +++ b/x-pack/plugins/apm/public/components/app/storage_explorer/index_lifecycle_phase_select.tsx @@ -24,13 +24,13 @@ export function IndexLifecyclePhaseSelect() { { value: IndexLifecyclePhaseSelectOption.All, label: i18n.translate( - 'xpack.apm.settings.storageExplorer.indexLifecyclePhase.all.label', + 'xpack.apm.storageExplorer.indexLifecyclePhase.all.label', { defaultMessage: 'All', } ), description: i18n.translate( - 'xpack.apm.settings.storageExplorer.indexLifecyclePhase.all.description', + 'xpack.apm.storageExplorer.indexLifecyclePhase.all.description', { defaultMessage: 'Search data in all lifecycle phases.', } @@ -39,13 +39,13 @@ export function IndexLifecyclePhaseSelect() { { value: IndexLifecyclePhaseSelectOption.Hot, label: i18n.translate( - 'xpack.apm.settings.storageExplorer.indexLifecyclePhase.hot.label', + 'xpack.apm.storageExplorer.indexLifecyclePhase.hot.label', { defaultMessage: 'Hot', } ), description: i18n.translate( - 'xpack.apm.settings.storageExplorer.indexLifecyclePhase.hot.description', + 'xpack.apm.storageExplorer.indexLifecyclePhase.hot.description', { defaultMessage: 'Holds your most-recent, most-frequently-searched data.', @@ -55,13 +55,13 @@ export function IndexLifecyclePhaseSelect() { { value: IndexLifecyclePhaseSelectOption.Warm, label: i18n.translate( - 'xpack.apm.settings.storageExplorer.indexLifecyclePhase.warm.label', + 'xpack.apm.storageExplorer.indexLifecyclePhase.warm.label', { defaultMessage: 'Warm', } ), description: i18n.translate( - 'xpack.apm.settings.storageExplorer.indexLifecyclePhase.warm.description', + 'xpack.apm.storageExplorer.indexLifecyclePhase.warm.description', { defaultMessage: 'Holds data from recent weeks. Updates are still allowed, but likely infrequent.', @@ -71,13 +71,13 @@ export function IndexLifecyclePhaseSelect() { { value: IndexLifecyclePhaseSelectOption.Cold, label: i18n.translate( - 'xpack.apm.settings.storageExplorer.indexLifecyclePhase.cold.label', + 'xpack.apm.storageExplorer.indexLifecyclePhase.cold.label', { defaultMessage: 'Cold', } ), description: i18n.translate( - 'xpack.apm.settings.storageExplorer.indexLifecyclePhase.cold.description', + 'xpack.apm.storageExplorer.indexLifecyclePhase.cold.description', { defaultMessage: 'While still searchable, this tier is typically optimized for lower storage costs rather than search speed.', @@ -87,13 +87,13 @@ export function IndexLifecyclePhaseSelect() { { value: IndexLifecyclePhaseSelectOption.Frozen, label: i18n.translate( - 'xpack.apm.settings.storageExplorer.indexLifecyclePhase.frozen.label', + 'xpack.apm.storageExplorer.indexLifecyclePhase.frozen.label', { defaultMessage: 'Frozen', } ), description: i18n.translate( - 'xpack.apm.settings.storageExplorer.indexLifecyclePhase.frozen.description', + 'xpack.apm.storageExplorer.indexLifecyclePhase.frozen.description', { defaultMessage: 'Holds data that are no longer being queried, or being queried rarely.', @@ -116,7 +116,7 @@ export function IndexLifecyclePhaseSelect() { return ( + {i18n.translate( + 'xpack.apm.storageExplorer.noPermissionToViewIndicesStatsTitle', + { + defaultMessage: 'You need permission to view index statistics', + } + )} + + } + body={ +

+ {i18n.translate( + 'xpack.apm.storageExplorer.noPermissionToViewIndicesStatsDescription', + { + defaultMessage: 'Contact your system administrator', + } + )} +

+ } + /> + ); +} diff --git a/x-pack/plugins/apm/public/components/app/storage_explorer/services_table/index.tsx b/x-pack/plugins/apm/public/components/app/storage_explorer/services_table/index.tsx index 950996540d2f9a..7f2dd2d8a096f1 100644 --- a/x-pack/plugins/apm/public/components/app/storage_explorer/services_table/index.tsx +++ b/x-pack/plugins/apm/public/components/app/storage_explorer/services_table/index.tsx @@ -106,7 +106,7 @@ export function ServicesTable() { { field: 'serviceName', name: i18n.translate( - 'xpack.apm.settings.storageExplorer.table.serviceColumnName', + 'xpack.apm.storageExplorer.table.serviceColumnName', { defaultMessage: 'Service', } @@ -140,7 +140,7 @@ export function ServicesTable() { { field: 'environment', name: i18n.translate( - 'xpack.apm.settings.storageExplorer.table.environmentColumnName', + 'xpack.apm.storageExplorer.table.environmentColumnName', { defaultMessage: 'Environment', } @@ -156,7 +156,7 @@ export function ServicesTable() { name: ( <> {i18n.translate( - 'xpack.apm.settings.storageExplorer.table.samplingColumnName', + 'xpack.apm.storageExplorer.table.samplingColumnName', { defaultMessage: 'Sample rate', } @@ -194,12 +194,9 @@ export function ServicesTable() { name: ( - {i18n.translate( - 'xpack.apm.settings.storageExplorer.table.expandRow', - { - defaultMessage: 'Expand row', - } - )} + {i18n.translate('xpack.apm.storageExplorer.table.expandRow', { + defaultMessage: 'Expand row', + })} ), @@ -210,18 +207,12 @@ export function ServicesTable() { onClick={() => toggleRowDetails(serviceName)} aria-label={ itemIdToExpandedRowMap[serviceName] - ? i18n.translate( - 'xpack.apm.settings.storageExplorer.table.collapse', - { - defaultMessage: 'Collapse', - } - ) - : i18n.translate( - 'xpack.apm.settings.storageExplorer.table.expand', - { - defaultMessage: 'Expand', - } - ) + ? i18n.translate('xpack.apm.storageExplorer.table.collapse', { + defaultMessage: 'Collapse', + }) + : i18n.translate('xpack.apm.storageExplorer.table.expand', { + defaultMessage: 'Expand', + }) } iconType={ itemIdToExpandedRowMap[serviceName] ? 'arrowUp' : 'arrowDown' @@ -234,12 +225,9 @@ export function ServicesTable() { return ( ); diff --git a/x-pack/plugins/apm/public/components/app/storage_explorer/services_table/size_label.tsx b/x-pack/plugins/apm/public/components/app/storage_explorer/services_table/size_label.tsx index 98a796df005e76..a8b562fa4b9fa1 100644 --- a/x-pack/plugins/apm/public/components/app/storage_explorer/services_table/size_label.tsx +++ b/x-pack/plugins/apm/public/components/app/storage_explorer/services_table/size_label.tsx @@ -13,14 +13,14 @@ export function SizeLabel() { return ( <> - {i18n.translate('xpack.apm.settings.storageExplorer.sizeLabel.title', { + {i18n.translate('xpack.apm.storageExplorer.sizeLabel.title', { defaultMessage: 'Size', })}{' '}

{i18n.translate( - 'xpack.apm.settings.storageExplorer.serviceDetails.title', + 'xpack.apm.storageExplorer.serviceDetails.title', { defaultMessage: 'Service storage details', } @@ -173,7 +173,7 @@ export function StorageDetailsPerService({ {i18n.translate( - 'xpack.apm.settings.storageExplorer.serviceDetails.serviceOverviewLink', + 'xpack.apm.storageExplorer.serviceDetails.serviceOverviewLink', { defaultMessage: 'Go to service overview', } diff --git a/x-pack/plugins/apm/public/components/app/storage_explorer/summary_stats.tsx b/x-pack/plugins/apm/public/components/app/storage_explorer/summary_stats.tsx new file mode 100644 index 00000000000000..c5ffb336ca5493 --- /dev/null +++ b/x-pack/plugins/apm/public/components/app/storage_explorer/summary_stats.tsx @@ -0,0 +1,201 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { + EuiPanel, + EuiFlexGroup, + EuiFlexItem, + EuiText, + useEuiFontSize, + EuiLink, + EuiLoadingSpinner, +} from '@elastic/eui'; +import { useEuiTheme } from '@elastic/eui'; +import { css } from '@emotion/react'; +import { useProgressiveFetcher } from '../../../hooks/use_progressive_fetcher'; +import { useTimeRange } from '../../../hooks/use_time_range'; +import { useApmParams } from '../../../hooks/use_apm_params'; +import { asDynamicBytes } from '../../../../common/utils/formatters'; +import { useApmRouter } from '../../../hooks/use_apm_router'; +import { useApmPluginContext } from '../../../context/apm_plugin/use_apm_plugin_context'; +import { FETCH_STATUS } from '../../../hooks/use_fetcher'; +import { asTransactionRate } from '../../../../common/utils/formatters'; + +const INITIAL_DATA = { + estimatedSize: 0, + dailyDataGeneration: 0, + tracesPerMinute: 0, + numberOfServices: 0, +}; + +export function SummaryStats() { + const router = useApmRouter(); + const { core } = useApmPluginContext(); + const { euiTheme } = useEuiTheme(); + + const { + query: { + rangeFrom, + rangeTo, + environment, + kuery, + indexLifecyclePhase, + comparisonEnabled, + }, + } = useApmParams('/storage-explorer'); + + const { start, end } = useTimeRange({ rangeFrom, rangeTo }); + + const serviceInventoryLink = router.link('/services', { + query: { + rangeFrom, + rangeTo, + environment, + comparisonEnabled, + kuery, + serviceGroup: '', + }, + }); + + const { data = INITIAL_DATA, status } = useProgressiveFetcher( + (callApmApi) => { + return callApmApi('GET /internal/apm/storage_explorer_summary_stats', { + params: { + query: { + indexLifecyclePhase, + environment, + kuery, + start, + end, + }, + }, + }); + }, + [indexLifecyclePhase, environment, kuery, start, end] + ); + + const loading = status === FETCH_STATUS.LOADING; + + return ( + + {loading && ( + + + + )} + {!loading && ( + + + + + + + + + + + + + + + {i18n.translate( + 'xpack.apm.storageExplorer.summary.serviceInventoryLink', + { + defaultMessage: 'Go to Service Inventory', + } + )} + + + + + {i18n.translate( + 'xpack.apm.storageExplorer.summary.indexManagementLink', + { + defaultMessage: 'Go to Index Management', + } + )} + + + + + + )} + + ); +} + +function SummaryMetric({ + label, + value, + color, +}: { + label: string; + value: string; + color: string; +}) { + const xxlFontSize = useEuiFontSize('xxl', { measurement: 'px' }); + const { euiTheme } = useEuiTheme(); + + return ( + + + {label} + + + {value} + + + ); +} diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/transaction_details_tabs.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/transaction_details_tabs.tsx index c8092689b9d2e3..742cd6f9e7a97e 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/transaction_details_tabs.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/transaction_details_tabs.tsx @@ -22,6 +22,7 @@ import { failedTransactionsCorrelationsTab } from './failed_transactions_correla import { latencyCorrelationsTab } from './latency_correlations_tab'; import { traceSamplesTab } from './trace_samples_tab'; import { useSampleChartSelection } from '../../../hooks/use_sample_chart_selection'; +import { FETCH_STATUS } from '../../../hooks/use_fetcher'; const tabs = [ traceSamplesTab, @@ -69,7 +70,7 @@ export function TransactionDetailsTabs() { sample.transactionId === transactionId && sample.traceId === traceId ); - if (!selectedSample) { + if (traceSamplesStatus === FETCH_STATUS.SUCCESS && !selectedSample) { // selected sample was not found. select a new one: const preferredSample = maybe(traceSamples[0]); @@ -84,7 +85,7 @@ export function TransactionDetailsTabs() { }), }); } - }, [history, traceSamples, transactionId, traceId]); + }, [history, traceSamples, transactionId, traceId, traceSamplesStatus]); return ( <> diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/index.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/index.tsx index f9642630766bd5..61b814a598e874 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/index.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/index.tsx @@ -91,12 +91,14 @@ export function WaterfallWithSummary({ - + {traceSamples.length > 0 && ( + + )} diff --git a/x-pack/plugins/apm/public/components/routing/home/storage_explorer.tsx b/x-pack/plugins/apm/public/components/routing/home/storage_explorer.tsx index b27cc2cf77bc85..c4bc86f766811e 100644 --- a/x-pack/plugins/apm/public/components/routing/home/storage_explorer.tsx +++ b/x-pack/plugins/apm/public/components/routing/home/storage_explorer.tsx @@ -9,6 +9,7 @@ import React from 'react'; import { EuiTitle, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import * as t from 'io-ts'; +import { EuiLink } from '@elastic/eui'; import { StorageExplorer } from '../../app/storage_explorer'; import { BetaBadge } from '../../shared/beta_badge'; import { ApmMainTemplate } from '../templates/apm_main_template'; @@ -28,26 +29,42 @@ export const storageExplorer = { href="/storage-explorer" > - - -

- {i18n.translate('xpack.apm.views.storageExplorer.title', { - defaultMessage: 'Storage explorer', - })} -

-
-
- - - -
- } + pageHeader={{ + alignItems: 'center', + pageTitle: ( + + + +

+ {i18n.translate('xpack.apm.views.storageExplorer.title', { + defaultMessage: 'Storage explorer', + })} +

+
+
+ + + +
+ ), + rightSideItems: [ + + {i18n.translate( + 'xpack.apm.views.storageExplorer.giveFeedback', + { + defaultMessage: 'Give feedback', + } + )} + , + ], + }} > diff --git a/x-pack/plugins/apm/public/hooks/use_transaction_trace_samples_fetcher.ts b/x-pack/plugins/apm/public/hooks/use_transaction_trace_samples_fetcher.ts index e04735821aaecd..f0906eef3ab094 100644 --- a/x-pack/plugins/apm/public/hooks/use_transaction_trace_samples_fetcher.ts +++ b/x-pack/plugins/apm/public/hooks/use_transaction_trace_samples_fetcher.ts @@ -46,9 +46,9 @@ export function useTransactionTraceSamplesFetcher({ status, error, } = useFetcher( - async (callApmApi) => { + (callApmApi) => { if (serviceName && start && end && transactionType && transactionName) { - const response = await callApmApi( + return callApmApi( 'GET /internal/apm/services/{serviceName}/transactions/traces/samples', { params: { @@ -70,8 +70,6 @@ export function useTransactionTraceSamplesFetcher({ }, } ); - - return response; } }, // the samples should not be refetched if the transactionId or traceId changes diff --git a/x-pack/plugins/apm/server/lib/connections/get_connection_stats/index.ts b/x-pack/plugins/apm/server/lib/connections/get_connection_stats/index.ts index 35d2a063325cf5..7c9781e08db318 100644 --- a/x-pack/plugins/apm/server/lib/connections/get_connection_stats/index.ts +++ b/x-pack/plugins/apm/server/lib/connections/get_connection_stats/index.ts @@ -12,7 +12,7 @@ import { joinByKey } from '../../../../common/utils/join_by_key'; import { Setup } from '../../helpers/setup_request'; import { getStats } from './get_stats'; import { getDestinationMap } from './get_destination_map'; -import { calculateThroughput } from '../../helpers/calculate_throughput'; +import { calculateThroughputWithRange } from '../../helpers/calculate_throughput'; import { withApmSpan } from '../../../utils/with_apm_span'; export function getConnectionStats({ @@ -124,7 +124,7 @@ export function getConnectionStats({ throughput: { value: mergedStats.value.count > 0 - ? calculateThroughput({ + ? calculateThroughputWithRange({ start, end, value: mergedStats.value.count, @@ -134,7 +134,11 @@ export function getConnectionStats({ x: point.x, y: point.count > 0 - ? calculateThroughput({ start, end, value: point.count }) + ? calculateThroughputWithRange({ + start, + end, + value: point.count, + }) : null, })), }, diff --git a/x-pack/plugins/apm/server/lib/helpers/calculate_throughput.ts b/x-pack/plugins/apm/server/lib/helpers/calculate_throughput.ts index 9c99f94f82861f..55f25c648b4df9 100644 --- a/x-pack/plugins/apm/server/lib/helpers/calculate_throughput.ts +++ b/x-pack/plugins/apm/server/lib/helpers/calculate_throughput.ts @@ -5,22 +5,6 @@ * 2.0. */ -/** - * @deprecated use calculateThroughputWithRange instead - */ -export function calculateThroughput({ - start, - end, - value, -}: { - start: number; - end: number; - value: number; -}) { - const durationAsMinutes = (end - start) / 1000 / 60; - return value / durationAsMinutes; -} - export function calculateThroughputWithRange({ start, end, diff --git a/x-pack/plugins/apm/server/lib/helpers/transactions/index.ts b/x-pack/plugins/apm/server/lib/helpers/transactions/index.ts index afaaf37c3362c3..cfd7f6102b00c3 100644 --- a/x-pack/plugins/apm/server/lib/helpers/transactions/index.ts +++ b/x-pack/plugins/apm/server/lib/helpers/transactions/index.ts @@ -11,6 +11,8 @@ import { SearchAggregatedTransactionSetting } from '../../../../common/aggregate import { TRANSACTION_DURATION, TRANSACTION_DURATION_HISTOGRAM, + TRANSACTION_ROOT, + PARENT_ID, } from '../../../../common/elasticsearch_fieldnames'; import { APMConfig } from '../../..'; import { APMEventClient } from '../create_es_client/create_apm_event_client'; @@ -106,3 +108,19 @@ export function getProcessorEventForTransactions( ? ProcessorEvent.metric : ProcessorEvent.transaction; } + +export function isRootTransaction(searchAggregatedTransactions: boolean) { + return searchAggregatedTransactions + ? { + term: { + [TRANSACTION_ROOT]: true, + }, + } + : { + bool: { + must_not: { + exists: { field: PARENT_ID }, + }, + }, + }; +} diff --git a/x-pack/plugins/apm/server/routes/services/get_service_instances/get_service_instances_transaction_statistics.ts b/x-pack/plugins/apm/server/routes/services/get_service_instances/get_service_instances_transaction_statistics.ts index 8231675baff8ef..d99a3f1d22da35 100644 --- a/x-pack/plugins/apm/server/routes/services/get_service_instances/get_service_instances_transaction_statistics.ts +++ b/x-pack/plugins/apm/server/routes/services/get_service_instances/get_service_instances_transaction_statistics.ts @@ -21,7 +21,7 @@ import { getDurationFieldForTransactions, getProcessorEventForTransactions, } from '../../../lib/helpers/transactions'; -import { calculateThroughput } from '../../../lib/helpers/calculate_throughput'; +import { calculateThroughputWithRange } from '../../../lib/helpers/calculate_throughput'; import { getBucketSizeForAggregatedTransactions } from '../../../lib/helpers/get_bucket_size_for_aggregated_transactions'; import { getLatencyAggregation, @@ -202,7 +202,7 @@ export async function getServiceInstancesTransactionStatistics< aggregation: latency, latencyAggregationType, }), - throughput: calculateThroughput({ + throughput: calculateThroughputWithRange({ start: startWithOffset, end: endWithOffset, value: count, diff --git a/x-pack/plugins/apm/server/routes/services/get_service_transaction_groups.ts b/x-pack/plugins/apm/server/routes/services/get_service_transaction_groups.ts index 985b5bc3e1dc45..cb068d5fb84426 100644 --- a/x-pack/plugins/apm/server/routes/services/get_service_transaction_groups.ts +++ b/x-pack/plugins/apm/server/routes/services/get_service_transaction_groups.ts @@ -20,7 +20,7 @@ import { getDurationFieldForTransactions, getProcessorEventForTransactions, } from '../../lib/helpers/transactions'; -import { calculateThroughput } from '../../lib/helpers/calculate_throughput'; +import { calculateThroughputWithRange } from '../../lib/helpers/calculate_throughput'; import { getLatencyAggregation, getLatencyValue, @@ -126,7 +126,7 @@ export async function getServiceTransactionGroups({ latencyAggregationType, aggregation: bucket.latency, }), - throughput: calculateThroughput({ + throughput: calculateThroughputWithRange({ start, end, value: bucket.doc_count, diff --git a/x-pack/plugins/apm/server/routes/services/get_services_detailed_statistics/get_service_transaction_detailed_statistics.ts b/x-pack/plugins/apm/server/routes/services/get_services_detailed_statistics/get_service_transaction_detailed_statistics.ts index 4a7c5c85436e1c..600d3c71f7e089 100644 --- a/x-pack/plugins/apm/server/routes/services/get_services_detailed_statistics/get_service_transaction_detailed_statistics.ts +++ b/x-pack/plugins/apm/server/routes/services/get_services_detailed_statistics/get_service_transaction_detailed_statistics.ts @@ -22,7 +22,7 @@ import { getDurationFieldForTransactions, getProcessorEventForTransactions, } from '../../../lib/helpers/transactions'; -import { calculateThroughput } from '../../../lib/helpers/calculate_throughput'; +import { calculateThroughputWithRange } from '../../../lib/helpers/calculate_throughput'; import { getBucketSizeForAggregatedTransactions } from '../../../lib/helpers/get_bucket_size_for_aggregated_transactions'; import { Setup } from '../../../lib/helpers/setup_request'; import { @@ -163,7 +163,7 @@ export async function getServiceTransactionDetailedStatistics({ throughput: topTransactionTypeBucket.timeseries.buckets.map( (dateBucket) => ({ x: dateBucket.key + offsetInMs, - y: calculateThroughput({ + y: calculateThroughputWithRange({ start, end, value: dateBucket.doc_count, diff --git a/x-pack/plugins/apm/server/routes/storage_explorer/get_service_statistics.ts b/x-pack/plugins/apm/server/routes/storage_explorer/get_service_statistics.ts index 548946288a5306..169bff0cd71134 100644 --- a/x-pack/plugins/apm/server/routes/storage_explorer/get_service_statistics.ts +++ b/x-pack/plugins/apm/server/routes/storage_explorer/get_service_statistics.ts @@ -56,7 +56,7 @@ async function getMainServiceStatistics({ }) { const { apmEventClient } = setup; - const [allIndicesStats, response] = await Promise.all([ + const [{ indices: allIndicesStats }, response] = await Promise.all([ getTotalIndicesStats({ context, setup }), apmEventClient.search('get_main_service_statistics', { apm: { @@ -69,6 +69,7 @@ async function getMainServiceStatistics({ }, body: { size: 0, + track_total_hits: false, query: { bool: { filter: [ diff --git a/x-pack/plugins/apm/server/routes/storage_explorer/get_size_timeseries.ts b/x-pack/plugins/apm/server/routes/storage_explorer/get_size_timeseries.ts index 2f0934566f62d4..f513efe059f713 100644 --- a/x-pack/plugins/apm/server/routes/storage_explorer/get_size_timeseries.ts +++ b/x-pack/plugins/apm/server/routes/storage_explorer/get_size_timeseries.ts @@ -59,7 +59,7 @@ export async function getSizeTimeseries({ searchAggregatedTransactions, }); - const [allIndicesStats, res] = await Promise.all([ + const [{ indices: allIndicesStats }, res] = await Promise.all([ getTotalIndicesStats({ setup, context }), apmEventClient.search('get_storage_timeseries', { apm: { @@ -72,6 +72,7 @@ export async function getSizeTimeseries({ }, body: { size: 0, + track_total_hits: false, query: { bool: { filter: [ @@ -94,7 +95,7 @@ export async function getSizeTimeseries({ services: { terms: { field: SERVICE_NAME, - size: 500, + size: 50, }, aggs: { storageTimeSeries: { diff --git a/x-pack/plugins/apm/server/routes/storage_explorer/get_storage_details_per_processor_event.ts b/x-pack/plugins/apm/server/routes/storage_explorer/get_storage_details_per_processor_event.ts index 474158b41736ff..95f575dff9600d 100644 --- a/x-pack/plugins/apm/server/routes/storage_explorer/get_storage_details_per_processor_event.ts +++ b/x-pack/plugins/apm/server/routes/storage_explorer/get_storage_details_per_processor_event.ts @@ -54,7 +54,7 @@ export async function getStorageDetailsPerProcessorEvent({ }) { const { apmEventClient } = setup; - const [allIndicesStats, response] = await Promise.all([ + const [{ indices: allIndicesStats }, response] = await Promise.all([ getTotalIndicesStats({ setup, context }), apmEventClient.search('get_storage_details_per_processor_event', { apm: { @@ -67,6 +67,7 @@ export async function getStorageDetailsPerProcessorEvent({ }, body: { size: 0, + track_total_hits: false, query: { bool: { filter: [ diff --git a/x-pack/plugins/apm/server/routes/storage_explorer/get_summary_statistics.ts b/x-pack/plugins/apm/server/routes/storage_explorer/get_summary_statistics.ts new file mode 100644 index 00000000000000..dfa510e8f08900 --- /dev/null +++ b/x-pack/plugins/apm/server/routes/storage_explorer/get_summary_statistics.ts @@ -0,0 +1,203 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ProcessorEvent } from '@kbn/observability-plugin/common'; +import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { + termQuery, + kqlQuery, + rangeQuery, +} from '@kbn/observability-plugin/server'; +import { + getTotalIndicesStats, + getEstimatedSizeForDocumentsInIndex, +} from './indices_stats_helpers'; +import { Setup } from '../../lib/helpers/setup_request'; +import { ApmPluginRequestHandlerContext } from '../typings'; +import { + IndexLifecyclePhaseSelectOption, + indexLifeCyclePhaseToDataTier, +} from '../../../common/storage_explorer_types'; +import { RandomSampler } from '../../lib/helpers/get_random_sampler'; +import { + SERVICE_NAME, + TIER, + INDEX, +} from '../../../common/elasticsearch_fieldnames'; +import { environmentQuery } from '../../../common/utils/environment_query'; +import { + getDocumentTypeFilterForTransactions, + getProcessorEventForTransactions, + getDurationFieldForTransactions, + isRootTransaction, +} from '../../lib/helpers/transactions'; +import { calculateThroughputWithRange } from '../../lib/helpers/calculate_throughput'; + +export async function getTracesPerMinute({ + setup, + indexLifecyclePhase, + start, + end, + environment, + kuery, + searchAggregatedTransactions, +}: { + setup: Setup; + indexLifecyclePhase: IndexLifecyclePhaseSelectOption; + start: number; + end: number; + environment: string; + kuery: string; + searchAggregatedTransactions: boolean; +}) { + const { apmEventClient } = setup; + + const response = await apmEventClient.search('get_traces_per_minute', { + apm: { + events: [getProcessorEventForTransactions(searchAggregatedTransactions)], + }, + body: { + size: 0, + track_total_hits: false, + query: { + bool: { + filter: [ + ...getDocumentTypeFilterForTransactions( + searchAggregatedTransactions + ), + ...environmentQuery(environment), + ...kqlQuery(kuery), + ...rangeQuery(start, end), + ...(indexLifecyclePhase !== IndexLifecyclePhaseSelectOption.All + ? termQuery( + TIER, + indexLifeCyclePhaseToDataTier[indexLifecyclePhase] + ) + : []), + isRootTransaction(searchAggregatedTransactions), + ], + }, + }, + aggs: { + traces_count: { + value_count: { + field: getDurationFieldForTransactions( + searchAggregatedTransactions + ), + }, + }, + }, + }, + }); + + return calculateThroughputWithRange({ + start, + end, + value: response?.aggregations?.traces_count.value ?? 0, + }); +} + +export async function getMainSummaryStats({ + setup, + context, + indexLifecyclePhase, + randomSampler, + start, + end, + environment, + kuery, +}: { + setup: Setup; + context: ApmPluginRequestHandlerContext; + indexLifecyclePhase: IndexLifecyclePhaseSelectOption; + randomSampler: RandomSampler; + start: number; + end: number; + environment: string; + kuery: string; +}) { + const { apmEventClient } = setup; + + const [{ indices: allIndicesStats }, res] = await Promise.all([ + getTotalIndicesStats({ context, setup }), + apmEventClient.search('get_storage_explorer_main_summary_stats', { + apm: { + events: [ + ProcessorEvent.span, + ProcessorEvent.transaction, + ProcessorEvent.error, + ProcessorEvent.metric, + ], + }, + body: { + size: 0, + track_total_hits: false, + query: { + bool: { + filter: [ + ...environmentQuery(environment), + ...kqlQuery(kuery), + ...rangeQuery(start, end), + ...(indexLifecyclePhase !== IndexLifecyclePhaseSelectOption.All + ? termQuery( + TIER, + indexLifeCyclePhaseToDataTier[indexLifecyclePhase] + ) + : []), + ] as QueryDslQueryContainer[], + }, + }, + aggs: { + services_count: { + cardinality: { + field: SERVICE_NAME, + }, + }, + sample: { + random_sampler: randomSampler, + aggs: { + indices: { + terms: { + field: INDEX, + size: 500, + }, + aggs: { + number_of_metric_docs: { + value_count: { + field: INDEX, + }, + }, + }, + }, + }, + }, + }, + }, + }), + ]); + + const estimatedSize = allIndicesStats + ? res.aggregations?.sample.indices.buckets.reduce((prev, curr) => { + return ( + prev + + getEstimatedSizeForDocumentsInIndex({ + allIndicesStats, + indexName: curr.key as string, + numberOfDocs: curr.number_of_metric_docs.value, + }) + ); + }, 0) ?? 0 + : 0; + + const durationAsDays = (end - start) / 1000 / 60 / 60 / 24; + + return { + numberOfServices: res.aggregations?.services_count.value ?? 0, + estimatedSize, + dailyDataGeneration: estimatedSize / durationAsDays, + }; +} diff --git a/x-pack/plugins/apm/server/routes/storage_explorer/get_total_transactions_per_service.ts b/x-pack/plugins/apm/server/routes/storage_explorer/get_total_transactions_per_service.ts index d479c54aae2c98..793c69ab71b4c7 100644 --- a/x-pack/plugins/apm/server/routes/storage_explorer/get_total_transactions_per_service.ts +++ b/x-pack/plugins/apm/server/routes/storage_explorer/get_total_transactions_per_service.ts @@ -54,6 +54,7 @@ export async function getTotalTransactionsPerService({ }, body: { size: 0, + track_total_hits: false, query: { bool: { filter: [ diff --git a/x-pack/plugins/apm/server/routes/storage_explorer/has_storage_explorer_privileges.ts b/x-pack/plugins/apm/server/routes/storage_explorer/has_storage_explorer_privileges.ts new file mode 100644 index 00000000000000..714c0eee1c62cb --- /dev/null +++ b/x-pack/plugins/apm/server/routes/storage_explorer/has_storage_explorer_privileges.ts @@ -0,0 +1,44 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { every } from 'lodash'; +import { uniq } from 'lodash'; +import { ApmPluginRequestHandlerContext } from '../typings'; +import { Setup } from '../../lib/helpers/setup_request'; + +export async function hasStorageExplorerPrivileges({ + context, + setup, +}: { + context: ApmPluginRequestHandlerContext; + setup: Setup; +}) { + const { + indices: { transaction, span, metric, error }, + } = setup; + + const names = uniq( + [transaction, span, metric, error].flatMap((indexPatternString) => + indexPatternString.split(',').map((indexPattern) => indexPattern.trim()) + ) + ); + + const esClient = (await context.core).elasticsearch.client; + const { index } = await esClient.asCurrentUser.security.hasPrivileges({ + body: { + index: [ + { + names, + privileges: ['monitor'], + }, + ], + }, + }); + + const hasPrivileges = every(index, 'monitor'); + return hasPrivileges; +} diff --git a/x-pack/plugins/apm/server/routes/storage_explorer/indices_stats_helpers.ts b/x-pack/plugins/apm/server/routes/storage_explorer/indices_stats_helpers.ts index 7abd7df856e30d..aa9e854cc4a291 100644 --- a/x-pack/plugins/apm/server/routes/storage_explorer/indices_stats_helpers.ts +++ b/x-pack/plugins/apm/server/routes/storage_explorer/indices_stats_helpers.ts @@ -21,10 +21,8 @@ export async function getTotalIndicesStats({ } = setup; const index = uniq([transaction, span, metric, error]).join(); const esClient = (await context.core).elasticsearch.client; - const indicesStats = (await esClient.asCurrentUser.indices.stats({ index })) - .indices; - - return indicesStats; + const totalStats = await esClient.asCurrentUser.indices.stats({ index }); + return totalStats; } export function getEstimatedSizeForDocumentsInIndex({ diff --git a/x-pack/plugins/apm/server/routes/storage_explorer/route.ts b/x-pack/plugins/apm/server/routes/storage_explorer/route.ts index 2441940f10bce1..7ee36fae5493cf 100644 --- a/x-pack/plugins/apm/server/routes/storage_explorer/route.ts +++ b/x-pack/plugins/apm/server/routes/storage_explorer/route.ts @@ -7,6 +7,8 @@ import * as t from 'io-ts'; import { ProcessorEvent } from '@kbn/observability-plugin/common'; +import Boom from '@hapi/boom'; +import { i18n } from '@kbn/i18n'; import { createApmServerRoute } from '../apm_routes/create_apm_server_route'; import { getSearchAggregatedTransactions } from '../../lib/helpers/transactions'; import { setupRequest } from '../../lib/helpers/setup_request'; @@ -22,6 +24,11 @@ import { AgentName } from '../../../typings/es_schemas/ui/fields/agent'; import { getStorageDetailsPerProcessorEvent } from './get_storage_details_per_processor_event'; import { getRandomSampler } from '../../lib/helpers/get_random_sampler'; import { getSizeTimeseries } from './get_size_timeseries'; +import { hasStorageExplorerPrivileges } from './has_storage_explorer_privileges'; +import { + getMainSummaryStats, + getTracesPerMinute, +} from './get_summary_statistics'; const storageExplorerRoute = createApmServerRoute({ endpoint: 'GET /internal/apm/storage_explorer', @@ -226,8 +233,117 @@ const storageChartRoute = createApmServerRoute({ }, }); +const storageExplorerPrivilegesRoute = createApmServerRoute({ + endpoint: 'GET /internal/apm/storage_explorer/privileges', + options: { tags: ['access:apm'] }, + + handler: async (resources): Promise<{ hasPrivileges: boolean }> => { + const { + plugins: { security }, + context, + } = resources; + + if (!security) { + throw Boom.internal(SECURITY_REQUIRED_MESSAGE); + } + + const setup = await setupRequest(resources); + const hasPrivileges = await hasStorageExplorerPrivileges({ + context, + setup, + }); + + return { hasPrivileges }; + }, +}); + +const storageExplorerSummaryStatsRoute = createApmServerRoute({ + endpoint: 'GET /internal/apm/storage_explorer_summary_stats', + options: { tags: ['access:apm'] }, + params: t.type({ + query: t.intersection([ + indexLifecyclePhaseRt, + probabilityRt, + environmentRt, + kueryRt, + rangeRt, + ]), + }), + handler: async ( + resources + ): Promise<{ + tracesPerMinute: number; + numberOfServices: number; + estimatedSize: number; + dailyDataGeneration: number; + }> => { + const { + params, + context, + request, + plugins: { security }, + } = resources; + + const { + query: { + indexLifecyclePhase, + probability, + environment, + kuery, + start, + end, + }, + } = params; + + const [setup, randomSampler] = await Promise.all([ + setupRequest(resources), + getRandomSampler({ security, request, probability }), + ]); + + const searchAggregatedTransactions = await getSearchAggregatedTransactions({ + apmEventClient: setup.apmEventClient, + config: setup.config, + kuery, + }); + + const [mainSummaryStats, tracesPerMinute] = await Promise.all([ + getMainSummaryStats({ + setup, + context, + indexLifecyclePhase, + randomSampler, + start, + end, + environment, + kuery, + }), + getTracesPerMinute({ + setup, + indexLifecyclePhase, + start, + end, + environment, + kuery, + searchAggregatedTransactions, + }), + ]); + + return { + ...mainSummaryStats, + tracesPerMinute, + }; + }, +}); + export const storageExplorerRouteRepository = { ...storageExplorerRoute, ...storageExplorerServiceDetailsRoute, ...storageChartRoute, + ...storageExplorerPrivilegesRoute, + ...storageExplorerSummaryStatsRoute, }; + +const SECURITY_REQUIRED_MESSAGE = i18n.translate( + 'xpack.apm.api.storageExplorer.securityRequired', + { defaultMessage: 'Security plugin is required' } +); diff --git a/x-pack/plugins/apm/server/routes/traces/get_top_traces_primary_stats.ts b/x-pack/plugins/apm/server/routes/traces/get_top_traces_primary_stats.ts index 17925a25a36c53..344cb8ff824c85 100644 --- a/x-pack/plugins/apm/server/routes/traces/get_top_traces_primary_stats.ts +++ b/x-pack/plugins/apm/server/routes/traces/get_top_traces_primary_stats.ts @@ -5,7 +5,6 @@ * 2.0. */ -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { sortBy } from 'lodash'; import { kqlQuery, @@ -23,14 +22,13 @@ import { getDurationFieldForTransactions, getDocumentTypeFilterForTransactions, getProcessorEventForTransactions, + isRootTransaction, } from '../../lib/helpers/transactions'; import { AGENT_NAME, - PARENT_ID, SERVICE_NAME, TRANSACTION_TYPE, TRANSACTION_NAME, - TRANSACTION_ROOT, } from '../../../common/elasticsearch_fieldnames'; import { RandomSampler } from '../../lib/helpers/get_random_sampler'; @@ -80,26 +78,7 @@ export async function getTopTracesPrimaryStats({ ...rangeQuery(start, end), ...environmentQuery(environment), ...kqlQuery(kuery), - ...(searchAggregatedTransactions - ? [ - { - term: { - [TRANSACTION_ROOT]: true, - }, - }, - ] - : []), - ] as estypes.QueryDslQueryContainer[], - must_not: [ - ...(!searchAggregatedTransactions - ? [ - { - exists: { - field: PARENT_ID, - }, - }, - ] - : []), + isRootTransaction(searchAggregatedTransactions), ], }, }, diff --git a/x-pack/plugins/enterprise_search/common/types/indices.ts b/x-pack/plugins/enterprise_search/common/types/indices.ts index d047ec9ba36d74..78831e16150046 100644 --- a/x-pack/plugins/enterprise_search/common/types/indices.ts +++ b/x-pack/plugins/enterprise_search/common/types/indices.ts @@ -36,9 +36,13 @@ export interface ElasticsearchIndex { export interface ConnectorIndex extends ElasticsearchIndex { connector: Connector; } -export interface CrawlerIndex extends ElasticsearchIndex { +export interface ConnectorCrawlerIndex extends ElasticsearchIndex { + connector: Connector; crawler: Crawler; +} +export interface CrawlerIndex extends ElasticsearchIndex { connector?: Connector; + crawler: Crawler; } export interface ElasticsearchIndexWithPrivileges extends ElasticsearchIndex { diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_scheduling.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_scheduling.tsx index ca9a415c4c958d..9c22ecd8572ef8 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_scheduling.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_scheduling.tsx @@ -34,7 +34,7 @@ import { UpdateConnectorSchedulingApiLogic } from '../../../api/connector/update import { SEARCH_INDEX_TAB_PATH } from '../../../routes'; import { IngestionStatus } from '../../../types'; -import { isConnectorIndex } from '../../../utils/indices'; +import { isConnectorIndex, isConnectorCrawlerIndex } from '../../../utils/indices'; import { IndexViewLogic } from '../index_view_logic'; @@ -61,7 +61,7 @@ export const ConnectorSchedulingComponent: React.FC = () => { frequency: schedulingInput?.interval ? cronToFrequency(schedulingInput.interval) : 'HOUR', }); - if (!isConnectorIndex(index)) { + if (!isConnectorIndex(index) && !isConnectorCrawlerIndex(index)) { return <>; } diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/search_index.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/search_index.tsx index 14be5f36b5e229..a376b4dd5bd48b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/search_index.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/search_index.tsx @@ -32,7 +32,6 @@ import { IndexCreatedCallout } from './components/index_created_callout/callout' import { IndexCreatedCalloutLogic } from './components/index_created_callout/callout_logic'; import { ConnectorConfiguration } from './connector/connector_configuration'; import { ConnectorSchedulingComponent } from './connector/connector_scheduling'; -import { AutomaticCrawlScheduler } from './crawler/automatic_crawl_scheduler/automatic_crawl_scheduler'; import { CrawlCustomSettingsFlyout } from './crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout'; import { SearchIndexDomainManagement } from './crawler/domain_management/domain_management'; import { SearchIndexDocuments } from './documents'; @@ -117,7 +116,7 @@ export const SearchIndex: React.FC = () => { }), }, { - content: , + content: , id: SearchIndexTabId.SCHEDULING, name: i18n.translate('xpack.enterpriseSearch.content.searchIndex.schedulingTabLabel', { defaultMessage: 'Scheduling', diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_indices/indices_table.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_indices/indices_table.tsx index 8ff7550b61ffda..b0602968352382 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_indices/indices_table.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_indices/indices_table.tsx @@ -161,7 +161,6 @@ export const IndicesTable: React.FC = ({ type: 'icon', }, { - available: (index) => !isCrawlerIndex(index), color: 'danger', description: 'Delete this index', icon: 'trash', diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/utils/indices.test.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/utils/indices.test.ts index ce6e443a250259..b023aff4b9e085 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/utils/indices.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/utils/indices.test.ts @@ -23,6 +23,7 @@ import { getLastUpdated, indexToViewIndex, isConnectorIndex, + isConnectorCrawlerIndex, isCrawlerIndex, isApiIndex, isConnectorViewIndex, @@ -144,6 +145,20 @@ describe('Indices util functions', () => { expect(isConnectorIndex(apiIndex)).toEqual(false); }); }); + describe('isConnectorCrawlerIndex', () => { + it('should return false for connector indices', () => { + expect(isConnectorCrawlerIndex(connectorIndex)).toEqual(false); + }); + it('should return false for connector-crawler indices', () => { + expect(isConnectorCrawlerIndex(connectorCrawlerIndex)).toEqual(true); + }); + it('should return false for crawler indices', () => { + expect(isConnectorCrawlerIndex(crawlerIndex)).toEqual(false); + }); + it('should return false for API indices', () => { + expect(isConnectorCrawlerIndex(apiIndex)).toEqual(false); + }); + }); describe('isCrawlerIndex', () => { it('should return true for crawler indices', () => { expect(isCrawlerIndex(crawlerIndex)).toEqual(true); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/utils/indices.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/utils/indices.ts index 9a17f7fe84f4dd..540ad2b2db69e2 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/utils/indices.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/utils/indices.ts @@ -13,6 +13,7 @@ import { ENTERPRISE_SEARCH_CONNECTOR_CRAWLER_SERVICE_TYPE } from '../../../../co import { SyncStatus, ConnectorStatus } from '../../../../common/types/connectors'; import { ConnectorIndex, + ConnectorCrawlerIndex, CrawlerIndex, ElasticsearchIndexWithIngestion, } from '../../../../common/types/indices'; @@ -36,6 +37,16 @@ export function isConnectorIndex( ); } +export function isConnectorCrawlerIndex( + index: ElasticsearchIndexWithIngestion | undefined +): index is ConnectorCrawlerIndex { + const crawlerIndex = index as CrawlerIndex; + return ( + !!crawlerIndex?.connector && + crawlerIndex.connector.service_type === ENTERPRISE_SEARCH_CONNECTOR_CRAWLER_SERVICE_TYPE + ); +} + export function isCrawlerIndex( index: ElasticsearchIndexWithIngestion | undefined ): index is CrawlerIndex { diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/product_selector.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/product_selector.tsx index 4cdeec3048f8b8..1bb6bb3777d81c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/product_selector.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/product_selector.tsx @@ -145,7 +145,7 @@ export const ProductSelector: React.FC = ({ defaultMessage: 'Set up a language client', } ), - to: docLinks.start, + to: docLinks.languageClients, }, { label: i18n.translate( diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/doc_links/doc_links.ts b/x-pack/plugins/enterprise_search/public/applications/shared/doc_links/doc_links.ts index ad7205ced01c27..ac5a5d05ef60f7 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/doc_links/doc_links.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/doc_links/doc_links.ts @@ -70,6 +70,7 @@ class DocLinks { public enterpriseSearchUsersAccess: string; public kibanaSecurity: string; public languageAnalyzers: string; + public languageClients: string; public licenseManagement: string; public pluginsIngestAttachment: string; public queryDsl: string; @@ -175,6 +176,7 @@ class DocLinks { this.enterpriseSearchUsersAccess = ''; this.kibanaSecurity = ''; this.languageAnalyzers = ''; + this.languageClients = ''; this.licenseManagement = ''; this.pluginsIngestAttachment = ''; this.queryDsl = ''; @@ -282,6 +284,7 @@ class DocLinks { this.enterpriseSearchUsersAccess = docLinks.links.enterpriseSearch.usersAccess; this.kibanaSecurity = docLinks.links.kibana.xpackSecurity; this.languageAnalyzers = docLinks.links.enterpriseSearch.languageAnalyzers; + this.languageClients = docLinks.links.enterpriseSearch.languageClients; this.licenseManagement = docLinks.links.enterpriseSearch.licenseManagement; this.pluginsIngestAttachment = docLinks.links.plugins.ingestAttachment; this.queryDsl = docLinks.links.query.queryDsl; diff --git a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/indices.ts b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/indices.ts index 183b7cb4b34385..fa56e19ed00a18 100644 --- a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/indices.ts +++ b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/indices.ts @@ -25,7 +25,11 @@ import { createIndexPipelineDefinitions } from '../../utils/create_pipeline_defi import { elasticsearchErrorHandler } from '../../utils/elasticsearch_error_handler'; import { isIndexNotFoundException } from '../../utils/identify_exceptions'; -export function registerIndexRoutes({ router, log }: RouteDependencies) { +export function registerIndexRoutes({ + router, + enterpriseSearchRequestHandler, + log, +}: RouteDependencies) { router.get( { path: '/internal/enterprise_search/search_indices', validate: false }, elasticsearchErrorHandler(log, async (context, _, response) => { @@ -141,15 +145,21 @@ export function registerIndexRoutes({ router, log }: RouteDependencies) { const { client } = (await context.core).elasticsearch; try { - const connector = await fetchConnectorByIndexName(client, indexName); const crawler = await fetchCrawlerByIndexName(client, indexName); + const connector = await fetchConnectorByIndexName(client, indexName); - if (connector) { - await deleteConnectorById(client, connector.id); + if (crawler) { + const crawlerRes = await enterpriseSearchRequestHandler.createRequest({ + path: `/api/ent/v1/internal/indices/${indexName}`, + })(context, request, response); + + if (crawlerRes.status !== 200) { + throw new Error(crawlerRes.payload.message); + } } - if (crawler) { - // do nothing for now because we don't have a way to delete a crawler yet + if (connector) { + await deleteConnectorById(client, connector.id); } await client.asCurrentUser.indices.delete({ index: indexName }); diff --git a/x-pack/plugins/event_log/server/es/cluster_client_adapter.mock.ts b/x-pack/plugins/event_log/server/es/cluster_client_adapter.mock.ts index 53a1b9501b4322..3cb1b8d12c0b14 100644 --- a/x-pack/plugins/event_log/server/es/cluster_client_adapter.mock.ts +++ b/x-pack/plugins/event_log/server/es/cluster_client_adapter.mock.ts @@ -25,6 +25,7 @@ const createClusterClientMock = () => { setIndexAliasToHidden: jest.fn(), queryEventsBySavedObjects: jest.fn(), aggregateEventsBySavedObjects: jest.fn(), + aggregateEventsWithAuthFilter: jest.fn(), shutdown: jest.fn(), }; return mock; diff --git a/x-pack/plugins/event_log/server/es/cluster_client_adapter.test.ts b/x-pack/plugins/event_log/server/es/cluster_client_adapter.test.ts index ed740a27b81e49..ea3e98e599ab52 100644 --- a/x-pack/plugins/event_log/server/es/cluster_client_adapter.test.ts +++ b/x-pack/plugins/event_log/server/es/cluster_client_adapter.test.ts @@ -13,11 +13,14 @@ import { getQueryBody, FindEventsOptionsBySavedObjectFilter, AggregateEventsOptionsBySavedObjectFilter, + AggregateEventsWithAuthFilter, + getQueryBodyWithAuthFilter, } from './cluster_client_adapter'; import { AggregateOptionsType, queryOptionsSchema } from '../event_log_client'; import { delay } from '../lib/delay'; import { pick, times } from 'lodash'; import type * as estypes from '@elastic/elasticsearch/lib/api/types'; +import { fromKueryExpression } from '@kbn/es-query'; type MockedLogger = ReturnType; @@ -728,6 +731,104 @@ describe('aggregateEventsBySavedObject', () => { }); }); +describe('aggregateEventsWithAuthFilter', () => { + const DEFAULT_OPTIONS = { + ...queryOptionsSchema.validate({}), + aggs: { + genericAgg: { + term: { + field: 'event.action', + size: 10, + }, + }, + }, + }; + + test('should call cluster with correct options', async () => { + clusterClient.search.mockResponse({ + aggregations: { + genericAgg: { + buckets: [ + { + key: 'execute', + doc_count: 10, + }, + { + key: 'execute-start', + doc_count: 10, + }, + { + key: 'new-instance', + doc_count: 2, + }, + ], + }, + }, + hits: { + hits: [], + total: { relation: 'eq', value: 0 }, + }, + took: 0, + timed_out: false, + _shards: { + failed: 0, + successful: 0, + total: 0, + skipped: 0, + }, + }); + const options: AggregateEventsWithAuthFilter = { + index: 'index-name', + namespace: 'namespace', + type: 'saved-object-type', + aggregateOptions: DEFAULT_OPTIONS as AggregateOptionsType, + authFilter: fromKueryExpression('test:test'), + }; + const result = await clusterClientAdapter.aggregateEventsWithAuthFilter(options); + + const [query] = clusterClient.search.mock.calls[0]; + expect(query).toEqual({ + index: 'index-name', + body: { + size: 0, + query: getQueryBodyWithAuthFilter( + logger, + options, + pick(options.aggregateOptions, ['start', 'end', 'filter']) + ), + aggs: { + genericAgg: { + term: { + field: 'event.action', + size: 10, + }, + }, + }, + }, + }); + expect(result).toEqual({ + aggregations: { + genericAgg: { + buckets: [ + { + key: 'execute', + doc_count: 10, + }, + { + key: 'execute-start', + doc_count: 10, + }, + { + key: 'new-instance', + doc_count: 2, + }, + ], + }, + }, + }); + }); +}); + describe('getQueryBody', () => { const options = { index: 'index-name', @@ -1411,6 +1512,431 @@ describe('getQueryBody', () => { }); }); +describe('getQueryBodyWithAuthFilter', () => { + const options = { + index: 'index-name', + namespace: undefined, + type: 'saved-object-type', + authFilter: fromKueryExpression('test:test'), + }; + test('should correctly build query with namespace filter when namespace is undefined', () => { + expect( + getQueryBodyWithAuthFilter(logger, options as AggregateEventsWithAuthFilter, {}) + ).toEqual({ + bool: { + filter: { + bool: { + minimum_should_match: 1, + should: [ + { + match: { + test: 'test', + }, + }, + ], + }, + }, + must: [ + { + nested: { + path: 'kibana.saved_objects', + query: { + bool: { + must: [ + { + term: { + 'kibana.saved_objects.rel': { + value: 'primary', + }, + }, + }, + { + term: { + 'kibana.saved_objects.type': { + value: 'saved-object-type', + }, + }, + }, + { + bool: { + must_not: { + exists: { + field: 'kibana.saved_objects.namespace', + }, + }, + }, + }, + ], + }, + }, + }, + }, + ], + }, + }); + }); + + test('should correctly build query with namespace filter when namespace is specified', () => { + expect( + getQueryBodyWithAuthFilter( + logger, + { ...options, namespace: 'namespace' } as AggregateEventsWithAuthFilter, + {} + ) + ).toEqual({ + bool: { + filter: { + bool: { + minimum_should_match: 1, + should: [ + { + match: { + test: 'test', + }, + }, + ], + }, + }, + must: [ + { + nested: { + path: 'kibana.saved_objects', + query: { + bool: { + must: [ + { + term: { + 'kibana.saved_objects.rel': { + value: 'primary', + }, + }, + }, + { + term: { + 'kibana.saved_objects.type': { + value: 'saved-object-type', + }, + }, + }, + { + term: { + 'kibana.saved_objects.namespace': { + value: 'namespace', + }, + }, + }, + ], + }, + }, + }, + }, + ], + }, + }); + }); + + test('should correctly build query when filter is specified', () => { + expect( + getQueryBodyWithAuthFilter(logger, options as AggregateEventsWithAuthFilter, { + filter: 'event.provider: alerting AND event.action:execute', + }) + ).toEqual({ + bool: { + filter: { + bool: { + filter: [ + { + bool: { + filter: [ + { + bool: { + minimum_should_match: 1, + should: [ + { + match: { + 'event.provider': 'alerting', + }, + }, + ], + }, + }, + { + bool: { + minimum_should_match: 1, + should: [ + { + match: { + 'event.action': 'execute', + }, + }, + ], + }, + }, + ], + }, + }, + { + bool: { + minimum_should_match: 1, + should: [ + { + match: { + test: 'test', + }, + }, + ], + }, + }, + ], + }, + }, + must: [ + { + nested: { + path: 'kibana.saved_objects', + query: { + bool: { + must: [ + { + term: { + 'kibana.saved_objects.rel': { + value: 'primary', + }, + }, + }, + { + term: { + 'kibana.saved_objects.type': { + value: 'saved-object-type', + }, + }, + }, + { + bool: { + must_not: { + exists: { + field: 'kibana.saved_objects.namespace', + }, + }, + }, + }, + ], + }, + }, + }, + }, + ], + }, + }); + }); + + test('should correctly build query when start is specified', () => { + expect( + getQueryBodyWithAuthFilter(logger, options as AggregateEventsWithAuthFilter, { + start: '2020-07-08T00:52:28.350Z', + }) + ).toEqual({ + bool: { + filter: { + bool: { + minimum_should_match: 1, + should: [ + { + match: { + test: 'test', + }, + }, + ], + }, + }, + must: [ + { + nested: { + path: 'kibana.saved_objects', + query: { + bool: { + must: [ + { + term: { + 'kibana.saved_objects.rel': { + value: 'primary', + }, + }, + }, + { + term: { + 'kibana.saved_objects.type': { + value: 'saved-object-type', + }, + }, + }, + { + bool: { + must_not: { + exists: { + field: 'kibana.saved_objects.namespace', + }, + }, + }, + }, + ], + }, + }, + }, + }, + { + range: { + '@timestamp': { + gte: '2020-07-08T00:52:28.350Z', + }, + }, + }, + ], + }, + }); + }); + + test('should correctly build query when end is specified', () => { + expect( + getQueryBodyWithAuthFilter(logger, options as AggregateEventsWithAuthFilter, { + end: '2020-07-10T00:52:28.350Z', + }) + ).toEqual({ + bool: { + filter: { + bool: { + minimum_should_match: 1, + should: [ + { + match: { + test: 'test', + }, + }, + ], + }, + }, + must: [ + { + nested: { + path: 'kibana.saved_objects', + query: { + bool: { + must: [ + { + term: { + 'kibana.saved_objects.rel': { + value: 'primary', + }, + }, + }, + { + term: { + 'kibana.saved_objects.type': { + value: 'saved-object-type', + }, + }, + }, + { + bool: { + must_not: { + exists: { + field: 'kibana.saved_objects.namespace', + }, + }, + }, + }, + ], + }, + }, + }, + }, + { + range: { + '@timestamp': { + lte: '2020-07-10T00:52:28.350Z', + }, + }, + }, + ], + }, + }); + }); + + test('should correctly build query when start and end are specified', () => { + expect( + getQueryBodyWithAuthFilter(logger, options as AggregateEventsWithAuthFilter, { + start: '2020-07-08T00:52:28.350Z', + end: '2020-07-10T00:52:28.350Z', + }) + ).toEqual({ + bool: { + filter: { + bool: { + minimum_should_match: 1, + should: [ + { + match: { + test: 'test', + }, + }, + ], + }, + }, + must: [ + { + nested: { + path: 'kibana.saved_objects', + query: { + bool: { + must: [ + { + term: { + 'kibana.saved_objects.rel': { + value: 'primary', + }, + }, + }, + { + term: { + 'kibana.saved_objects.type': { + value: 'saved-object-type', + }, + }, + }, + { + bool: { + must_not: { + exists: { + field: 'kibana.saved_objects.namespace', + }, + }, + }, + }, + ], + }, + }, + }, + }, + { + range: { + '@timestamp': { + gte: '2020-07-08T00:52:28.350Z', + }, + }, + }, + { + range: { + '@timestamp': { + lte: '2020-07-10T00:52:28.350Z', + }, + }, + }, + ], + }, + }); + }); +}); + type RetryableFunction = () => boolean; const RETRY_UNTIL_DEFAULT_COUNT = 20; diff --git a/x-pack/plugins/event_log/server/es/cluster_client_adapter.ts b/x-pack/plugins/event_log/server/es/cluster_client_adapter.ts index d097bb9ee1957d..e807899d6290b3 100644 --- a/x-pack/plugins/event_log/server/es/cluster_client_adapter.ts +++ b/x-pack/plugins/event_log/server/es/cluster_client_adapter.ts @@ -12,7 +12,7 @@ import type { PublicMethodsOf } from '@kbn/utility-types'; import { Logger, ElasticsearchClient } from '@kbn/core/server'; import util from 'util'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import { fromKueryExpression, toElasticsearchQuery } from '@kbn/es-query'; +import { fromKueryExpression, toElasticsearchQuery, KueryNode, nodeBuilder } from '@kbn/es-query'; import { IEvent, IValidatedEvent, SAVED_OBJECT_REL_PRIMARY } from '../types'; import { AggregateOptionsType, FindOptionsType, QueryOptionsType } from '../event_log_client'; import { ParsedIndexAlias } from './init'; @@ -50,6 +50,14 @@ interface QueryOptionsEventsBySavedObjectFilter { legacyIds?: string[]; } +export interface AggregateEventsWithAuthFilter { + index: string; + namespace: string | undefined; + type: string; + authFilter: KueryNode; + aggregateOptions: AggregateOptionsType; +} + export type FindEventsOptionsBySavedObjectFilter = QueryOptionsEventsBySavedObjectFilter & { findOptions: FindOptionsType; }; @@ -415,6 +423,126 @@ export class ClusterClientAdapter { + const { index, type, aggregateOptions } = queryOptions; + const { aggs } = aggregateOptions; + + const esClient = await this.elasticsearchClientPromise; + + const query = getQueryBodyWithAuthFilter( + this.logger, + queryOptions, + pick(queryOptions.aggregateOptions, ['start', 'end', 'filter']) + ); + + const body: estypes.SearchRequest['body'] = { + size: 0, + query, + aggs, + }; + + try { + const { aggregations } = await esClient.search({ + index, + body, + }); + return { + aggregations, + }; + } catch (err) { + throw new Error( + `querying for Event Log by for type "${type}" and auth filter failed with: ${err.message}` + ); + } + } +} + +export function getQueryBodyWithAuthFilter( + logger: Logger, + opts: AggregateEventsWithAuthFilter, + queryOptions: QueryOptionsType +) { + const { namespace, type, authFilter } = opts; + const { start, end, filter } = queryOptions ?? {}; + + const namespaceQuery = getNamespaceQuery(namespace); + let dslFilterQuery: estypes.QueryDslBoolQuery['filter']; + try { + const filterKueryNode = filter ? fromKueryExpression(filter) : null; + const queryFilter = filterKueryNode + ? nodeBuilder.and([filterKueryNode, authFilter as KueryNode]) + : authFilter; + dslFilterQuery = queryFilter ? toElasticsearchQuery(queryFilter) : undefined; + } catch (err) { + logger.debug( + `esContext: Invalid kuery syntax for the filter (${filter}) error: ${JSON.stringify({ + message: err.message, + statusCode: err.statusCode, + })}` + ); + throw err; + } + + const savedObjectsQueryMust: estypes.QueryDslQueryContainer[] = [ + { + term: { + 'kibana.saved_objects.rel': { + value: SAVED_OBJECT_REL_PRIMARY, + }, + }, + }, + { + term: { + 'kibana.saved_objects.type': { + value: type, + }, + }, + }, + // @ts-expect-error undefined is not assignable as QueryDslTermQuery value + namespaceQuery, + ]; + + const musts: estypes.QueryDslQueryContainer[] = [ + { + nested: { + path: 'kibana.saved_objects', + query: { + bool: { + must: reject(savedObjectsQueryMust, isUndefined), + }, + }, + }, + }, + ]; + + if (start) { + musts.push({ + range: { + '@timestamp': { + gte: start, + }, + }, + }); + } + if (end) { + musts.push({ + range: { + '@timestamp': { + lte: end, + }, + }, + }); + } + + return { + bool: { + ...(dslFilterQuery ? { filter: dslFilterQuery } : {}), + must: reject(musts, isUndefined), + }, + }; } function getNamespaceQuery(namespace?: string) { @@ -446,9 +574,15 @@ export function getQueryBody( const { start, end, filter } = queryOptions ?? {}; const namespaceQuery = getNamespaceQuery(namespace); + let filterKueryNode; + try { + filterKueryNode = JSON.parse(filter ?? ''); + } catch (e) { + filterKueryNode = filter ? fromKueryExpression(filter) : null; + } let dslFilterQuery: estypes.QueryDslBoolQuery['filter']; try { - dslFilterQuery = filter ? toElasticsearchQuery(fromKueryExpression(filter)) : undefined; + dslFilterQuery = filterKueryNode ? toElasticsearchQuery(filterKueryNode) : undefined; } catch (err) { logger.debug( `esContext: Invalid kuery syntax for the filter (${filter}) error: ${JSON.stringify({ @@ -492,6 +626,7 @@ export function getQueryBody( ]; const shouldQuery = []; + shouldQuery.push({ bool: { must: [ diff --git a/x-pack/plugins/event_log/server/event_log_client.mock.ts b/x-pack/plugins/event_log/server/event_log_client.mock.ts index 7129bb9513856d..0e11ded65be658 100644 --- a/x-pack/plugins/event_log/server/event_log_client.mock.ts +++ b/x-pack/plugins/event_log/server/event_log_client.mock.ts @@ -11,6 +11,7 @@ const createEventLogClientMock = () => { const mock: jest.Mocked = { findEventsBySavedObjectIds: jest.fn(), aggregateEventsBySavedObjectIds: jest.fn(), + aggregateEventsWithAuthFilter: jest.fn(), }; return mock; }; diff --git a/x-pack/plugins/event_log/server/event_log_client.test.ts b/x-pack/plugins/event_log/server/event_log_client.test.ts index 89f6df538aca57..5e4fd08819fb33 100644 --- a/x-pack/plugins/event_log/server/event_log_client.test.ts +++ b/x-pack/plugins/event_log/server/event_log_client.test.ts @@ -12,6 +12,7 @@ import { contextMock } from './es/context.mock'; import { merge } from 'lodash'; import moment from 'moment'; import { IClusterClientAdapter } from './es/cluster_client_adapter'; +import { fromKueryExpression } from '@kbn/es-query'; const expectedSavedObject = { id: 'saved-object-id', @@ -240,6 +241,38 @@ describe('EventLogStart', () => { }); }); }); + describe('aggregateEventsWithAuthFilter', () => { + const testAuthFilter = fromKueryExpression('test:test'); + test('throws when no aggregation is defined in options', async () => { + savedObjectGetter.mockResolvedValueOnce(expectedSavedObject); + await expect( + eventLogClient.aggregateEventsWithAuthFilter('saved-object-type', testAuthFilter) + ).rejects.toMatchInlineSnapshot(`[Error: No aggregation defined!]`); + }); + test('calls aggregateEventsWithAuthFilter with given aggregation', async () => { + savedObjectGetter.mockResolvedValueOnce(expectedSavedObject); + await eventLogClient.aggregateEventsWithAuthFilter('saved-object-type', testAuthFilter, { + aggs: { myAgg: {} }, + }); + expect(esContext.esAdapter.aggregateEventsWithAuthFilter).toHaveBeenCalledWith({ + index: esContext.esNames.indexPattern, + namespace: undefined, + type: 'saved-object-type', + authFilter: testAuthFilter, + aggregateOptions: { + aggs: { myAgg: {} }, + page: 1, + per_page: 10, + sort: [ + { + sort_field: '@timestamp', + sort_order: 'asc', + }, + ], + }, + }); + }); + }); }); function fakeEvent(overrides = {}) { diff --git a/x-pack/plugins/event_log/server/event_log_client.ts b/x-pack/plugins/event_log/server/event_log_client.ts index 13aa2e3eadec00..e23b5f137eef18 100644 --- a/x-pack/plugins/event_log/server/event_log_client.ts +++ b/x-pack/plugins/event_log/server/event_log_client.ts @@ -12,6 +12,7 @@ import { IClusterClient, KibanaRequest } from '@kbn/core/server'; import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { SpacesServiceStart } from '@kbn/spaces-plugin/server'; +import { KueryNode } from '@kbn/core-saved-objects-api-server'; import { EsContext } from './es'; import { IEventLogClient } from './types'; import { QueryEventsBySavedObjectResult } from './es/cluster_client_adapter'; @@ -138,6 +139,32 @@ export class EventLogClient implements IEventLogClient { }); } + public async aggregateEventsWithAuthFilter( + type: string, + authFilter: KueryNode, + options?: AggregateOptionsType + ) { + if (!authFilter) { + throw new Error('No authorization filter defined!'); + } + + const aggs = options?.aggs; + if (!aggs) { + throw new Error('No aggregation defined!'); + } + + // validate other query options separately from + const aggregateOptions = queryOptionsSchema.validate(omit(options, 'aggs') ?? {}); + + return await this.esContext.esAdapter.aggregateEventsWithAuthFilter({ + index: this.esContext.esNames.indexPattern, + namespace: await this.getNamespace(), + type, + authFilter, + aggregateOptions: { ...aggregateOptions, aggs } as AggregateOptionsType, + }); + } + private async getNamespace() { const space = await this.spacesService?.getActiveSpace(this.request); return space && this.spacesService?.spaceIdToNamespace(space.id); diff --git a/x-pack/plugins/event_log/server/types.ts b/x-pack/plugins/event_log/server/types.ts index 3291f162c09df0..d610a8bff9c2ac 100644 --- a/x-pack/plugins/event_log/server/types.ts +++ b/x-pack/plugins/event_log/server/types.ts @@ -7,6 +7,7 @@ import { schema, TypeOf } from '@kbn/config-schema'; import type { IRouter, KibanaRequest, CustomRequestHandlerContext } from '@kbn/core/server'; +import { KueryNode } from '@kbn/es-query'; export type { IEvent, IValidatedEvent } from '../generated/schemas'; export { EventSchema, ECS_VERSION } from '../generated/schemas'; @@ -62,6 +63,11 @@ export interface IEventLogClient { options?: Partial, legacyIds?: string[] ): Promise; + aggregateEventsWithAuthFilter( + type: string, + authFilter: KueryNode, + options?: Partial + ): Promise; } export interface IEventLogger { diff --git a/x-pack/plugins/fleet/common/openapi/bundled.json b/x-pack/plugins/fleet/common/openapi/bundled.json index 9b1789ed6c5d52..1f953e9010d9bc 100644 --- a/x-pack/plugins/fleet/common/openapi/bundled.json +++ b/x-pack/plugins/fleet/common/openapi/bundled.json @@ -2731,28 +2731,37 @@ } }, "requestBody": { + "description": "You should use inputs as an object and not use the deprecated inputs array.", "content": { "application/json": { "schema": { - "allOf": [ + "oneOf": [ { - "$ref": "#/components/schemas/new_package_policy" + "$ref": "#/components/schemas/simplified_package_policy" }, { - "type": "object", - "properties": { - "id": { - "type": "string" - } - } - }, - { - "type": "object", - "properties": { - "force": { - "type": "boolean" + "deprecated": true, + "allOf": [ + { + "$ref": "#/components/schemas/new_package_policy" + }, + { + "type": "object", + "properties": { + "id": { + "type": "string" + } + } + }, + { + "type": "object", + "properties": { + "force": { + "type": "boolean" + } + } } - } + ] } ] } @@ -3054,18 +3063,25 @@ "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "item": { - "$ref": "#/components/schemas/package_policy" + "oneOf": [ + { + "$ref": "#/components/schemas/simplified_package_policy" }, - "sucess": { - "type": "boolean" + { + "type": "object", + "properties": { + "item": { + "$ref": "#/components/schemas/package_policy" + }, + "sucess": { + "type": "boolean" + } + }, + "required": [ + "item", + "sucess" + ] } - }, - "required": [ - "item", - "sucess" ] } } @@ -4335,6 +4351,72 @@ "warning" ] }, + "agent_component_status": { + "title": "Agent component status", + "type": "string", + "enum": [ + "starting", + "configuring", + "healthy", + "degraded", + "failed", + "stopping", + "stopped" + ] + }, + "agent_component_unit_type": { + "title": "Agent component unit type", + "type": "string", + "enum": [ + "input", + "output" + ] + }, + "agent_component_unit": { + "title": "Agent component unit", + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "$ref": "#/components/schemas/agent_component_unit_type" + }, + "status": { + "$ref": "#/components/schemas/agent_component_status" + }, + "message": { + "type": "string" + }, + "payload": { + "type": "object" + } + } + }, + "agent_component": { + "title": "Agent component", + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string" + }, + "status": { + "$ref": "#/components/schemas/agent_component_status" + }, + "message": { + "type": "string" + }, + "units": { + "type": "array", + "items": { + "$ref": "#/components/schemas/agent_component_unit" + } + } + } + }, "agent": { "title": "Agent", "type": "object", @@ -4386,6 +4468,12 @@ }, "default_api_key": { "type": "string" + }, + "components": { + "type": "array", + "items": { + "$ref": "#/components/schemas/agent_component" + } } }, "required": [ @@ -4841,6 +4929,96 @@ "created_at" ] }, + "simplified_package_policy": { + "title": "Simplified Package Policy", + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Package policy unique identifier" + }, + "name": { + "type": "string", + "description": "Package policy name (should be unique)" + }, + "description": { + "type": "string", + "description": "Package policy description" + }, + "namespace": { + "type": "string", + "description": "namespace by default \"default\"" + }, + "policy_id": { + "type": "string", + "description": "Agent policy ID where that package policy will be added" + }, + "package": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Package name" + }, + "version": { + "type": "string", + "description": "Package version" + } + }, + "required": [ + "name", + "version" + ] + }, + "vars": { + "type": "object", + "description": "Package root level variable (see integration documentation for more information)" + }, + "inputs": { + "type": "object", + "description": "Package policy inputs (see integration documentation to know what inputs are available)", + "additionalProperties": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "enable or disable that input, (default to true)" + }, + "vars": { + "type": "object", + "description": "Input level variable (see integration documentation for more information)" + }, + "streams": { + "type": "object", + "description": "Input streams (see integration documentation to know what streams are available)", + "additionalProperties": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "enable or disable that stream, (default to true)" + }, + "vars": { + "type": "object", + "description": "Stream level variable (see integration documentation for more information)" + } + } + } + } + } + } + }, + "force": { + "type": "boolean", + "description": "Force package policy creation even if package is not verified, or if the agent policy is managed." + } + }, + "required": [ + "name", + "policy_id", + "package" + ] + }, "upgrade_diff": { "title": "Package policy Upgrade dryrun", "type": "array", diff --git a/x-pack/plugins/fleet/common/openapi/bundled.yaml b/x-pack/plugins/fleet/common/openapi/bundled.yaml index 906b039e83509f..b52604ab73d726 100644 --- a/x-pack/plugins/fleet/common/openapi/bundled.yaml +++ b/x-pack/plugins/fleet/common/openapi/bundled.yaml @@ -1686,19 +1686,25 @@ paths: required: - item requestBody: + description: >- + You should use inputs as an object and not use the deprecated inputs + array. content: application/json: schema: - allOf: - - $ref: '#/components/schemas/new_package_policy' - - type: object - properties: - id: - type: string - - type: object - properties: - force: - type: boolean + oneOf: + - $ref: '#/components/schemas/simplified_package_policy' + - deprecated: true + allOf: + - $ref: '#/components/schemas/new_package_policy' + - type: object + properties: + id: + type: string + - type: object + properties: + force: + type: boolean parameters: - $ref: '#/components/parameters/kbn_xsrf' /package_policies/_bulk_get: @@ -1884,15 +1890,17 @@ paths: content: application/json: schema: - type: object - properties: - item: - $ref: '#/components/schemas/package_policy' - sucess: - type: boolean - required: - - item - - sucess + oneOf: + - $ref: '#/components/schemas/simplified_package_policy' + - type: object + properties: + item: + $ref: '#/components/schemas/package_policy' + sucess: + type: boolean + required: + - item + - sucess parameters: - $ref: '#/components/parameters/kbn_xsrf' delete: @@ -2727,6 +2735,53 @@ components: - online - inactive - warning + agent_component_status: + title: Agent component status + type: string + enum: + - starting + - configuring + - healthy + - degraded + - failed + - stopping + - stopped + agent_component_unit_type: + title: Agent component unit type + type: string + enum: + - input + - output + agent_component_unit: + title: Agent component unit + type: object + properties: + id: + type: string + type: + $ref: '#/components/schemas/agent_component_unit_type' + status: + $ref: '#/components/schemas/agent_component_status' + message: + type: string + payload: + type: object + agent_component: + title: Agent component + type: object + properties: + id: + type: string + type: + type: string + status: + $ref: '#/components/schemas/agent_component_status' + message: + type: string + units: + type: array + items: + $ref: '#/components/schemas/agent_component_unit' agent: title: Agent type: object @@ -2763,6 +2818,10 @@ components: $ref: '#/components/schemas/agent_status' default_api_key: type: string + components: + type: array + items: + $ref: '#/components/schemas/agent_component' required: - type - active @@ -3062,6 +3121,83 @@ components: - api_key - active - created_at + simplified_package_policy: + title: Simplified Package Policy + type: object + properties: + id: + type: string + description: Package policy unique identifier + name: + type: string + description: Package policy name (should be unique) + description: + type: string + description: Package policy description + namespace: + type: string + description: namespace by default "default" + policy_id: + type: string + description: Agent policy ID where that package policy will be added + package: + type: object + properties: + name: + type: string + description: Package name + version: + type: string + description: Package version + required: + - name + - version + vars: + type: object + description: >- + Package root level variable (see integration documentation for more + information) + inputs: + type: object + description: >- + Package policy inputs (see integration documentation to know what + inputs are available) + additionalProperties: + type: object + properties: + enabled: + type: boolean + description: enable or disable that input, (default to true) + vars: + type: object + description: >- + Input level variable (see integration documentation for more + information) + streams: + type: object + description: >- + Input streams (see integration documentation to know what + streams are available) + additionalProperties: + type: object + properties: + enabled: + type: boolean + description: enable or disable that stream, (default to true) + vars: + type: object + description: >- + Stream level variable (see integration documentation for + more information) + force: + type: boolean + description: >- + Force package policy creation even if package is not verified, or if + the agent policy is managed. + required: + - name + - policy_id + - package upgrade_diff: title: Package policy Upgrade dryrun type: array diff --git a/x-pack/plugins/fleet/common/openapi/components/schemas/simplified_package_policy.yaml b/x-pack/plugins/fleet/common/openapi/components/schemas/simplified_package_policy.yaml new file mode 100644 index 00000000000000..6ff537386f05b6 --- /dev/null +++ b/x-pack/plugins/fleet/common/openapi/components/schemas/simplified_package_policy.yaml @@ -0,0 +1,64 @@ +title: Simplified Package Policy +type: object +properties: + id: + type: string + description: Package policy unique identifier + name: + type: string + description: Package policy name (should be unique) + description: + type: string + description: Package policy description + namespace: + type: string + description: namespace by default "default" + policy_id: + type: string + description: Agent policy ID where that package policy will be added + package: + type: object + properties: + name: + type: string + description: Package name + version: + type: string + description: Package version + required: + - name + - version + vars: + type: object + description: Package root level variable (see integration documentation for more information) + inputs: + type: object + description: Package policy inputs (see integration documentation to know what inputs are available) + additionalProperties: + type: object + properties: + enabled: + type: boolean + description: enable or disable that input, (default to true) + vars: + type: object + description: Input level variable (see integration documentation for more information) + streams: + type: object + description: Input streams (see integration documentation to know what streams are available) + additionalProperties: + type: object + properties: + enabled: + type: boolean + description: enable or disable that stream, (default to true) + vars: + type: object + description: Stream level variable (see integration documentation for more information) + force: + type: boolean + description: Force package policy creation even if package is not verified, or if the agent policy is managed. +required: + - name + - policy_id + - package diff --git a/x-pack/plugins/fleet/common/openapi/paths/package_policies.yaml b/x-pack/plugins/fleet/common/openapi/paths/package_policies.yaml index 1d1263f16b01df..10e4fba447bc51 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/package_policies.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/package_policies.yaml @@ -41,18 +41,23 @@ post: required: - item requestBody: + description: You should use inputs as an object and not use the deprecated inputs array. content: application/json: schema: - allOf: - - $ref: ../components/schemas/new_package_policy.yaml - - type: object - properties: - id: - type: string - - type: object - properties: - force: - type: boolean + oneOf: + - $ref: ../components/schemas/simplified_package_policy.yaml + # Using inputs as an array is deprecated + - deprecated: true + allOf: + - $ref: ../components/schemas/new_package_policy.yaml + - type: object + properties: + id: + type: string + - type: object + properties: + force: + type: boolean parameters: - $ref: ../components/headers/kbn_xsrf.yaml diff --git a/x-pack/plugins/fleet/common/openapi/paths/package_policies@{package_policy_id}.yaml b/x-pack/plugins/fleet/common/openapi/paths/package_policies@{package_policy_id}.yaml index 8dda212c409eb1..bf3e0e0a6eeff6 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/package_policies@{package_policy_id}.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/package_policies@{package_policy_id}.yaml @@ -34,15 +34,17 @@ put: content: application/json: schema: - type: object - properties: - item: - $ref: ../components/schemas/package_policy.yaml - sucess: - type: boolean - required: - - item - - sucess + oneOf: + - $ref: ../components/schemas/simplified_package_policy.yaml + - type: object + properties: + item: + $ref: ../components/schemas/package_policy.yaml + sucess: + type: boolean + required: + - item + - sucess parameters: - $ref: ../components/headers/kbn_xsrf.yaml delete: diff --git a/x-pack/plugins/fleet/common/services/agent_status.ts b/x-pack/plugins/fleet/common/services/agent_status.ts index 7dbfb88192da80..7d7b11f5d8a5d8 100644 --- a/x-pack/plugins/fleet/common/services/agent_status.ts +++ b/x-pack/plugins/fleet/common/services/agent_status.ts @@ -41,7 +41,7 @@ export function getAgentStatus(agent: Agent | FleetServerAgent): AgentStatus { ? agent.policy_revision_idx : undefined; - if (!policyRevision || (agent.upgrade_started_at && !agent.upgraded_at)) { + if (!policyRevision || (agent.upgrade_started_at && agent.upgrade_status !== 'completed')) { return 'updating'; } if (intervalsSinceLastCheckIn >= offlineTimeoutIntervalCount) { @@ -78,7 +78,7 @@ export function buildKueryForOfflineAgents(path: string = '') { } export function buildKueryForUpgradingAgents(path: string = '') { - return `(${path}upgrade_started_at:*) and not (${path}upgraded_at:*)`; + return `(${path}upgrade_started_at:*) and not (${path}upgrade_status:completed)`; } export function buildKueryForUpdatingAgents(path: string = '') { diff --git a/x-pack/plugins/fleet/common/services/is_agent_upgradeable.ts b/x-pack/plugins/fleet/common/services/is_agent_upgradeable.ts index 2a523d1a2eabb7..c4c9fa7e75a692 100644 --- a/x-pack/plugins/fleet/common/services/is_agent_upgradeable.ts +++ b/x-pack/plugins/fleet/common/services/is_agent_upgradeable.ts @@ -25,7 +25,7 @@ export function isAgentUpgradeable(agent: Agent, kibanaVersion: string, versionT return false; } // check that the agent is not already in the process of updating - if (agent.upgrade_started_at && !agent.upgraded_at) { + if (agent.upgrade_started_at && agent.upgrade_status !== 'completed') { return false; } if (versionToUpgrade !== undefined) { diff --git a/x-pack/plugins/fleet/common/types/models/agent.ts b/x-pack/plugins/fleet/common/types/models/agent.ts index 3bcadfc863f847..9924413cb16bf4 100644 --- a/x-pack/plugins/fleet/common/types/models/agent.ts +++ b/x-pack/plugins/fleet/common/types/models/agent.ts @@ -67,8 +67,9 @@ interface AgentBase { enrolled_at: string; unenrolled_at?: string; unenrollment_started_at?: string; - upgraded_at?: string | null; + upgraded_at?: string; upgrade_started_at?: string | null; + upgrade_status?: 'started' | 'completed'; access_api_key_id?: string; default_api_key?: string; default_api_key_id?: string; @@ -158,11 +159,15 @@ export interface FleetServerAgent { /** * Date/time the Elastic Agent was last upgraded */ - upgraded_at?: string | null; + upgraded_at?: string; /** * Date/time the Elastic Agent started the current upgrade */ upgrade_started_at?: string | null; + /** + * Upgrade status + */ + upgrade_status?: 'started' | 'completed'; /** * ID of the API key the Elastic Agent must used to contact Fleet Server */ @@ -197,7 +202,7 @@ export interface FleetServerAgent { */ last_checkin?: string; /** - * Lst checkin status + * Last checkin status */ last_checkin_status?: 'error' | 'online' | 'degraded' | 'updating'; /** diff --git a/x-pack/plugins/fleet/server/routes/package_policy/handlers.ts b/x-pack/plugins/fleet/server/routes/package_policy/handlers.ts index 9d1cbac194bcb8..657e802844bc69 100644 --- a/x-pack/plugins/fleet/server/routes/package_policy/handlers.ts +++ b/x-pack/plugins/fleet/server/routes/package_policy/handlers.ts @@ -37,8 +37,11 @@ import type { } from '../../../common/types'; import { installationStatuses } from '../../../common/constants'; import { defaultIngestErrorHandler, PackagePolicyNotFoundError } from '../../errors'; -import { getInstallations } from '../../services/epm/packages'; +import { getInstallations, getPackageInfo } from '../../services/epm/packages'; import { PACKAGES_SAVED_OBJECT_TYPE, SO_SEARCH_LIMIT } from '../../constants'; +import { simplifiedPackagePolicytoNewPackagePolicy } from '../../services/package_policies/simplified_package_policy_helper'; + +import type { SimplifiedPackagePolicy } from '../../services/package_policies/simplified_package_policy_helper'; export const getPackagePoliciesHandler: RequestHandler< undefined, @@ -163,6 +166,17 @@ export const getOrphanedPackagePolicies: RequestHandler = } }; +function isSimplifiedCreatePackagePolicyRequest( + body: Omit, 'force' | 'package'> +): body is SimplifiedPackagePolicy { + // If `inputs` is not defined or if it's a non-array, the request body is using the new simplified API + if (body.inputs && Array.isArray(body.inputs)) { + return false; + } + + return true; +} + export const createPackagePolicyHandler: FleetRequestHandler< undefined, undefined, @@ -173,15 +187,30 @@ export const createPackagePolicyHandler: FleetRequestHandler< const soClient = fleetContext.epm.internalSoClient; const esClient = coreContext.elasticsearch.client.asInternalUser; const user = appContextService.getSecurity()?.authc.getCurrentUser(request) || undefined; - const { force, ...newPolicy } = request.body; - // TODO Remove deprecated APIs https://github.com/elastic/kibana/issues/121485 - delete newPolicy.output_id; + const { force, package: pkg, ...newPolicy } = request.body; + if ('output_id' in newPolicy) { + // TODO Remove deprecated APIs https://github.com/elastic/kibana/issues/121485 + delete newPolicy.output_id; + } const spaceId = fleetContext.spaceId; try { - const newPackagePolicy = await packagePolicyService.enrichPolicyWithDefaultsFromPackage( - soClient, - newPolicy as NewPackagePolicy - ); + let newPackagePolicy: NewPackagePolicy; + if (isSimplifiedCreatePackagePolicyRequest(newPolicy)) { + if (!pkg) { + throw new Error('Package is required'); + } + const pkgInfo = await getPackageInfo({ + savedObjectsClient: soClient, + pkgName: pkg.name, + pkgVersion: pkg.version, + }); + newPackagePolicy = simplifiedPackagePolicytoNewPackagePolicy(newPolicy, pkgInfo); + } else { + newPackagePolicy = await packagePolicyService.enrichPolicyWithDefaultsFromPackage(soClient, { + ...newPolicy, + package: pkg, + } as NewPackagePolicy); + } const newData = await packagePolicyService.runExternalCallbacks( 'packagePolicyCreate', @@ -235,37 +264,58 @@ export const updatePackagePolicyHandler: RequestHandler< throw Boom.notFound('Package policy not found'); } - const { force, ...body } = request.body; - // TODO Remove deprecated APIs https://github.com/elastic/kibana/issues/121485 - delete body.output_id; - // removed fields not recognized by schema - const packagePolicyInputs = packagePolicy.inputs.map((input) => { - const newInput = { - ...input, - streams: input.streams.map((stream) => { - const newStream = { ...stream }; - delete newStream.compiled_stream; - return newStream; - }), - }; - delete newInput.compiled_input; - return newInput; - }); - - // listing down accepted properties, because loaded packagePolicy contains some that are not accepted in update - let newData = { - ...body, - name: body.name ?? packagePolicy.name, - description: body.description ?? packagePolicy.description, - namespace: body.namespace ?? packagePolicy.namespace, - policy_id: body.policy_id ?? packagePolicy.policy_id, - enabled: body.enabled ?? packagePolicy.enabled, - package: body.package ?? packagePolicy.package, - inputs: body.inputs ?? packagePolicyInputs, - vars: body.vars ?? packagePolicy.vars, - } as NewPackagePolicy; - try { + const { force, package: pkg, ...body } = request.body; + // TODO Remove deprecated APIs https://github.com/elastic/kibana/issues/121485 + if ('output_id' in body) { + delete body.output_id; + } + + let newData: NewPackagePolicy; + + if ( + body.inputs && + isSimplifiedCreatePackagePolicyRequest(body as unknown as SimplifiedPackagePolicy) + ) { + if (!pkg) { + throw new Error('package is required'); + } + const pkgInfo = await getPackageInfo({ + savedObjectsClient: soClient, + pkgName: pkg.name, + pkgVersion: pkg.version, + }); + newData = simplifiedPackagePolicytoNewPackagePolicy( + body as unknown as SimplifiedPackagePolicy, + pkgInfo + ); + } else { + // removed fields not recognized by schema + const packagePolicyInputs = packagePolicy.inputs.map((input) => { + const newInput = { + ...input, + streams: input.streams.map((stream) => { + const newStream = { ...stream }; + delete newStream.compiled_stream; + return newStream; + }), + }; + delete newInput.compiled_input; + return newInput; + }); + // listing down accepted properties, because loaded packagePolicy contains some that are not accepted in update + newData = { + ...body, + name: body.name ?? packagePolicy.name, + description: body.description ?? packagePolicy.description, + namespace: body.namespace ?? packagePolicy.namespace, + policy_id: body.policy_id ?? packagePolicy.policy_id, + enabled: 'enabled' in body ? body.enabled ?? packagePolicy.enabled : packagePolicy.enabled, + package: pkg ?? packagePolicy.package, + inputs: body.inputs ?? packagePolicyInputs, + vars: body.vars ?? packagePolicy.vars, + } as NewPackagePolicy; + } newData = await packagePolicyService.runExternalCallbacks( 'packagePolicyUpdate', newData, diff --git a/x-pack/plugins/fleet/server/services/agents/actions.ts b/x-pack/plugins/fleet/server/services/agents/actions.ts index c4f3530892543a..f0e2d059a98a86 100644 --- a/x-pack/plugins/fleet/server/services/agents/actions.ts +++ b/x-pack/plugins/fleet/server/services/agents/actions.ts @@ -139,8 +139,8 @@ export async function cancelAgentAction(esClient: ElasticsearchClient, actionId: hit._source.agents.map((agentId) => ({ agentId, data: { - upgraded_at: null, upgrade_started_at: null, + upgrade_status: 'completed', }, })) ); diff --git a/x-pack/plugins/fleet/server/services/agents/upgrade.ts b/x-pack/plugins/fleet/server/services/agents/upgrade.ts index efe363b2b46b85..1083e8f728ee19 100644 --- a/x-pack/plugins/fleet/server/services/agents/upgrade.ts +++ b/x-pack/plugins/fleet/server/services/agents/upgrade.ts @@ -67,8 +67,8 @@ export async function sendUpgradeAgentAction({ type: 'UPGRADE', }); await updateAgent(esClient, agentId, { - upgraded_at: null, upgrade_started_at: now, + upgrade_status: 'started', }); } @@ -207,8 +207,8 @@ async function upgradeBatch( agentsToUpdate.map((agent) => ({ agentId: agent.id, data: { - upgraded_at: null, upgrade_started_at: now, + upgrade_status: 'started', }, })) ); diff --git a/x-pack/plugins/fleet/server/services/package_policies/__snapshots__/simplified_package_policy_helper.test.ts.snap b/x-pack/plugins/fleet/server/services/package_policies/__snapshots__/simplified_package_policy_helper.test.ts.snap new file mode 100644 index 00000000000000..200eed919407ed --- /dev/null +++ b/x-pack/plugins/fleet/server/services/package_policies/__snapshots__/simplified_package_policy_helper.test.ts.snap @@ -0,0 +1,239 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`toPackagePolicy With nginx package should work 1`] = ` +Object { + "description": "Test description", + "enabled": true, + "inputs": Array [ + Object { + "enabled": true, + "policy_template": "nginx", + "streams": Array [ + Object { + "data_stream": Object { + "dataset": "nginx.access", + "type": "logs", + }, + "enabled": true, + "vars": Object { + "ignore_older": Object { + "type": "text", + "value": "72h", + }, + "paths": Object { + "type": "text", + "value": Array [ + "/var/log/nginx/access.log*", + ], + }, + "preserve_original_event": Object { + "type": "bool", + "value": false, + }, + "processors": Object { + "type": "yaml", + "value": undefined, + }, + "tags": Object { + "type": "text", + "value": Array [ + "nginx-access", + ], + }, + }, + }, + Object { + "data_stream": Object { + "dataset": "nginx.error", + "type": "logs", + }, + "enabled": true, + "vars": Object { + "ignore_older": Object { + "type": "text", + "value": "72h", + }, + "paths": Object { + "type": "text", + "value": Array [ + "/var/log/nginx/error.log*", + ], + }, + "preserve_original_event": Object { + "type": "bool", + "value": false, + }, + "processors": Object { + "type": "yaml", + "value": undefined, + }, + "tags": Object { + "type": "text", + "value": Array [ + "test", + "nginx-error", + ], + }, + }, + }, + ], + "type": "logfile", + }, + Object { + "enabled": false, + "policy_template": "nginx", + "streams": Array [ + Object { + "data_stream": Object { + "dataset": "nginx.access", + "type": "logs", + }, + "enabled": false, + "vars": Object { + "interval": Object { + "type": "text", + "value": "10s", + }, + "preserve_original_event": Object { + "type": "bool", + "value": false, + }, + "processors": Object { + "type": "yaml", + "value": undefined, + }, + "search": Object { + "type": "text", + "value": "search sourcetype=nginx:plus:access", + }, + "tags": Object { + "type": "text", + "value": Array [ + "forwarded", + "nginx-access", + ], + }, + }, + }, + Object { + "data_stream": Object { + "dataset": "nginx.error", + "type": "logs", + }, + "enabled": false, + "vars": Object { + "interval": Object { + "type": "text", + "value": "10s", + }, + "preserve_original_event": Object { + "type": "bool", + "value": false, + }, + "processors": Object { + "type": "yaml", + "value": undefined, + }, + "search": Object { + "type": "text", + "value": "search sourcetype=nginx:plus:error", + }, + "tags": Object { + "type": "text", + "value": Array [ + "forwarded", + "nginx-error", + ], + }, + }, + }, + ], + "type": "httpjson", + "vars": Object { + "password": Object { + "type": "password", + "value": undefined, + }, + "ssl": Object { + "type": "yaml", + "value": "#certificate_authorities: +# - | +# -----BEGIN CERTIFICATE----- +# MIIDCjCCAfKgAwIBAgITJ706Mu2wJlKckpIvkWxEHvEyijANBgkqhkiG9w0BAQsF +# ADAUMRIwEAYDVQQDDAlsb2NhbGhvc3QwIBcNMTkwNzIyMTkyOTA0WhgPMjExOTA2 +# MjgxOTI5MDRaMBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEB +# BQADggEPADCCAQoCggEBANce58Y/JykI58iyOXpxGfw0/gMvF0hUQAcUrSMxEO6n +# fZRA49b4OV4SwWmA3395uL2eB2NB8y8qdQ9muXUdPBWE4l9rMZ6gmfu90N5B5uEl +# 94NcfBfYOKi1fJQ9i7WKhTjlRkMCgBkWPkUokvBZFRt8RtF7zI77BSEorHGQCk9t +# /D7BS0GJyfVEhftbWcFEAG3VRcoMhF7kUzYwp+qESoriFRYLeDWv68ZOvG7eoWnP +# PsvZStEVEimjvK5NSESEQa9xWyJOmlOKXhkdymtcUd/nXnx6UTCFgnkgzSdTWV41 +# CI6B6aJ9svCTI2QuoIq2HxX/ix7OvW1huVmcyHVxyUECAwEAAaNTMFEwHQYDVR0O +# BBYEFPwN1OceFGm9v6ux8G+DZ3TUDYxqMB8GA1UdIwQYMBaAFPwN1OceFGm9v6ux +# 8G+DZ3TUDYxqMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAG5D +# 874A4YI7YUwOVsVAdbWtgp1d0zKcPRR+r2OdSbTAV5/gcS3jgBJ3i1BN34JuDVFw +# 3DeJSYT3nxy2Y56lLnxDeF8CUTUtVQx3CuGkRg1ouGAHpO/6OqOhwLLorEmxi7tA +# H2O8mtT0poX5AnOAhzVy7QW0D/k4WaoLyckM5hUa6RtvgvLxOwA0U+VGurCDoctu +# 8F4QOgTAWyh8EZIwaKCliFRSynDpv3JTUwtfZkxo6K6nce1RhCWFAsMvDZL8Dgc0 +# yvgJ38BRsFOtkRuAGSf6ZUwTO8JJRRIFnpUzXflAnGivK9M13D5GEQMmIl6U9Pvk +# sxSmbIUfc2SGJGCJD4I= +# -----END CERTIFICATE----- +", + }, + "token": Object { + "type": "password", + "value": undefined, + }, + "url": Object { + "type": "text", + "value": "https://server.example.com:8089", + }, + "username": Object { + "type": "text", + "value": undefined, + }, + }, + }, + Object { + "enabled": true, + "policy_template": "nginx", + "streams": Array [ + Object { + "data_stream": Object { + "dataset": "nginx.stubstatus", + "type": "metrics", + }, + "enabled": true, + "vars": Object { + "period": Object { + "type": "text", + "value": "10s", + }, + "server_status_path": Object { + "type": "text", + "value": "/nginx_status", + }, + }, + }, + ], + "type": "nginx/metrics", + "vars": Object { + "hosts": Object { + "type": "text", + "value": Array [ + "http://127.0.0.1:80", + ], + }, + }, + }, + ], + "name": "nginx-1", + "namespace": "default", + "package": Object { + "name": "nginx", + "title": "Nginx", + "version": "1.5.0", + }, + "policy_id": "policy123", + "vars": undefined, +} +`; diff --git a/x-pack/plugins/fleet/server/services/package_policies/fixtures/package_info/nginx_1.5.0.json b/x-pack/plugins/fleet/server/services/package_policies/fixtures/package_info/nginx_1.5.0.json new file mode 100644 index 00000000000000..ad2418c052120d --- /dev/null +++ b/x-pack/plugins/fleet/server/services/package_policies/fixtures/package_info/nginx_1.5.0.json @@ -0,0 +1,658 @@ +{ + "name": "nginx", + "title": "Nginx", + "version": "1.5.0", + "release": "ga", + "description": "Collect logs and metrics from Nginx HTTP servers with Elastic Agent.", + "type": "integration", + "download": "/epr/nginx/nginx-1.5.0.zip", + "path": "/package/nginx/1.5.0", + "icons": [ + { + "src": "/img/logo_nginx.svg", + "path": "/package/nginx/1.5.0/img/logo_nginx.svg", + "title": "logo nginx", + "size": "32x32", + "type": "image/svg+xml" + } + ], + "conditions": { "kibana": { "version": "^8.0.0" } }, + "owner": { "github": "elastic/obs-service-integrations" }, + "categories": ["web", "security"], + "format_version": "1.0.0", + "readme": "/package/nginx/1.5.0/docs/README.md", + "license": "basic", + "screenshots": [ + { + "src": "/img/nginx-metrics-overview.png", + "path": "/package/nginx/1.5.0/img/nginx-metrics-overview.png", + "title": "Nginx metrics overview", + "size": "3360x2302", + "type": "image/png" + }, + { + "src": "/img/nginx-logs-access-error.png", + "path": "/package/nginx/1.5.0/img/nginx-logs-access-error.png", + "title": "Nginx access and error logs", + "size": "3360x3590", + "type": "image/png" + }, + { + "src": "/img/nginx-logs-overview.png", + "path": "/package/nginx/1.5.0/img/nginx-logs-overview.png", + "title": "Nginx logs overview", + "size": "3360x3590", + "type": "image/png" + } + ], + "assets": { + "kibana": { + "dashboard": [ + { + "pkgkey": "nginx-1.5.0", + "service": "kibana", + "type": "dashboard", + "file": "nginx-023d2930-f1a5-11e7-a9ef-93c69af7b129.json", + "path": "nginx-1.5.0/kibana/dashboard/nginx-023d2930-f1a5-11e7-a9ef-93c69af7b129.json" + }, + { + "pkgkey": "nginx-1.5.0", + "service": "kibana", + "type": "dashboard", + "file": "nginx-046212a0-a2a1-11e7-928f-5dbe6f6f5519.json", + "path": "nginx-1.5.0/kibana/dashboard/nginx-046212a0-a2a1-11e7-928f-5dbe6f6f5519.json" + }, + { + "pkgkey": "nginx-1.5.0", + "service": "kibana", + "type": "dashboard", + "file": "nginx-55a9e6e0-a29e-11e7-928f-5dbe6f6f5519.json", + "path": "nginx-1.5.0/kibana/dashboard/nginx-55a9e6e0-a29e-11e7-928f-5dbe6f6f5519.json" + } + ], + "map": [ + { + "pkgkey": "nginx-1.5.0", + "service": "kibana", + "type": "map", + "file": "nginx-4576daa0-e1da-11ec-baf0-970634a1784d.json", + "path": "nginx-1.5.0/kibana/map/nginx-4576daa0-e1da-11ec-baf0-970634a1784d.json" + } + ], + "ml_module": [ + { + "pkgkey": "nginx-1.5.0", + "service": "kibana", + "type": "ml_module", + "file": "nginx-Logs-ml.json", + "path": "nginx-1.5.0/kibana/ml_module/nginx-Logs-ml.json" + } + ], + "search": [ + { + "pkgkey": "nginx-1.5.0", + "service": "kibana", + "type": "search", + "file": "nginx-6d9e66d0-a1f0-11e7-928f-5dbe6f6f5519.json", + "path": "nginx-1.5.0/kibana/search/nginx-6d9e66d0-a1f0-11e7-928f-5dbe6f6f5519.json" + }, + { + "pkgkey": "nginx-1.5.0", + "service": "kibana", + "type": "search", + "file": "nginx-9eb25600-a1f0-11e7-928f-5dbe6f6f5519.json", + "path": "nginx-1.5.0/kibana/search/nginx-9eb25600-a1f0-11e7-928f-5dbe6f6f5519.json" + }, + { + "pkgkey": "nginx-1.5.0", + "service": "kibana", + "type": "search", + "file": "nginx-Logs-Nginx-integration.json", + "path": "nginx-1.5.0/kibana/search/nginx-Logs-Nginx-integration.json" + } + ], + "visualization": [ + { + "pkgkey": "nginx-1.5.0", + "service": "kibana", + "type": "visualization", + "file": "nginx-0dd6f320-a29f-11e7-928f-5dbe6f6f5519.json", + "path": "nginx-1.5.0/kibana/visualization/nginx-0dd6f320-a29f-11e7-928f-5dbe6f6f5519.json" + }, + { + "pkgkey": "nginx-1.5.0", + "service": "kibana", + "type": "visualization", + "file": "nginx-1cfb1a80-a1f4-11e7-928f-5dbe6f6f5519.json", + "path": "nginx-1.5.0/kibana/visualization/nginx-1cfb1a80-a1f4-11e7-928f-5dbe6f6f5519.json" + }, + { + "pkgkey": "nginx-1.5.0", + "service": "kibana", + "type": "visualization", + "file": "nginx-46322e50-a1f6-11e7-928f-5dbe6f6f5519.json", + "path": "nginx-1.5.0/kibana/visualization/nginx-46322e50-a1f6-11e7-928f-5dbe6f6f5519.json" + }, + { + "pkgkey": "nginx-1.5.0", + "service": "kibana", + "type": "visualization", + "file": "nginx-47a8e0f0-f1a4-11e7-a9ef-93c69af7b129.json", + "path": "nginx-1.5.0/kibana/visualization/nginx-47a8e0f0-f1a4-11e7-a9ef-93c69af7b129.json" + }, + { + "pkgkey": "nginx-1.5.0", + "service": "kibana", + "type": "visualization", + "file": "nginx-555df8a0-f1a1-11e7-a9ef-93c69af7b129.json", + "path": "nginx-1.5.0/kibana/visualization/nginx-555df8a0-f1a1-11e7-a9ef-93c69af7b129.json" + }, + { + "pkgkey": "nginx-1.5.0", + "service": "kibana", + "type": "visualization", + "file": "nginx-7cc9ea40-3af8-11eb-94b7-0dab91df36a6.json", + "path": "nginx-1.5.0/kibana/visualization/nginx-7cc9ea40-3af8-11eb-94b7-0dab91df36a6.json" + }, + { + "pkgkey": "nginx-1.5.0", + "service": "kibana", + "type": "visualization", + "file": "nginx-823b3c80-3af9-11eb-94b7-0dab91df36a6.json", + "path": "nginx-1.5.0/kibana/visualization/nginx-823b3c80-3af9-11eb-94b7-0dab91df36a6.json" + }, + { + "pkgkey": "nginx-1.5.0", + "service": "kibana", + "type": "visualization", + "file": "nginx-9184fa00-a1f5-11e7-928f-5dbe6f6f5519.json", + "path": "nginx-1.5.0/kibana/visualization/nginx-9184fa00-a1f5-11e7-928f-5dbe6f6f5519.json" + }, + { + "pkgkey": "nginx-1.5.0", + "service": "kibana", + "type": "visualization", + "file": "nginx-9484ecf0-3af5-11eb-94b7-0dab91df36a6.json", + "path": "nginx-1.5.0/kibana/visualization/nginx-9484ecf0-3af5-11eb-94b7-0dab91df36a6.json" + }, + { + "pkgkey": "nginx-1.5.0", + "service": "kibana", + "type": "visualization", + "file": "nginx-97109780-a2a5-11e7-928f-5dbe6f6f5519.json", + "path": "nginx-1.5.0/kibana/visualization/nginx-97109780-a2a5-11e7-928f-5dbe6f6f5519.json" + }, + { + "pkgkey": "nginx-1.5.0", + "service": "kibana", + "type": "visualization", + "file": "nginx-Access-Browsers.json", + "path": "nginx-1.5.0/kibana/visualization/nginx-Access-Browsers.json" + }, + { + "pkgkey": "nginx-1.5.0", + "service": "kibana", + "type": "visualization", + "file": "nginx-Access-Map.json", + "path": "nginx-1.5.0/kibana/visualization/nginx-Access-Map.json" + }, + { + "pkgkey": "nginx-1.5.0", + "service": "kibana", + "type": "visualization", + "file": "nginx-Access-OSes.json", + "path": "nginx-1.5.0/kibana/visualization/nginx-Access-OSes.json" + }, + { + "pkgkey": "nginx-1.5.0", + "service": "kibana", + "type": "visualization", + "file": "nginx-a1d92240-f1a1-11e7-a9ef-93c69af7b129.json", + "path": "nginx-1.5.0/kibana/visualization/nginx-a1d92240-f1a1-11e7-a9ef-93c69af7b129.json" + }, + { + "pkgkey": "nginx-1.5.0", + "service": "kibana", + "type": "visualization", + "file": "nginx-b70b1b20-a1f4-11e7-928f-5dbe6f6f5519.json", + "path": "nginx-1.5.0/kibana/visualization/nginx-b70b1b20-a1f4-11e7-928f-5dbe6f6f5519.json" + }, + { + "pkgkey": "nginx-1.5.0", + "service": "kibana", + "type": "visualization", + "file": "nginx-d763a570-f1a1-11e7-a9ef-93c69af7b129.json", + "path": "nginx-1.5.0/kibana/visualization/nginx-d763a570-f1a1-11e7-a9ef-93c69af7b129.json" + }, + { + "pkgkey": "nginx-1.5.0", + "service": "kibana", + "type": "visualization", + "file": "nginx-dcbffe30-f1a4-11e7-a9ef-93c69af7b129.json", + "path": "nginx-1.5.0/kibana/visualization/nginx-dcbffe30-f1a4-11e7-a9ef-93c69af7b129.json" + }, + { + "pkgkey": "nginx-1.5.0", + "service": "kibana", + "type": "visualization", + "file": "nginx-e302b5a0-3afb-11eb-94b7-0dab91df36a6.json", + "path": "nginx-1.5.0/kibana/visualization/nginx-e302b5a0-3afb-11eb-94b7-0dab91df36a6.json" + }, + { + "pkgkey": "nginx-1.5.0", + "service": "kibana", + "type": "visualization", + "file": "nginx-ea7f9e10-3af6-11eb-94b7-0dab91df36a6.json", + "path": "nginx-1.5.0/kibana/visualization/nginx-ea7f9e10-3af6-11eb-94b7-0dab91df36a6.json" + } + ] + }, + "elasticsearch": { + "ingest_pipeline": [ + { + "pkgkey": "nginx-1.5.0", + "service": "elasticsearch", + "type": "ingest_pipeline", + "file": "default.yml", + "dataset": "access", + "path": "nginx-1.5.0/data_stream/access/elasticsearch/ingest_pipeline/default.yml" + }, + { + "pkgkey": "nginx-1.5.0", + "service": "elasticsearch", + "type": "ingest_pipeline", + "file": "third-party.yml", + "dataset": "access", + "path": "nginx-1.5.0/data_stream/access/elasticsearch/ingest_pipeline/third-party.yml" + }, + { + "pkgkey": "nginx-1.5.0", + "service": "elasticsearch", + "type": "ingest_pipeline", + "file": "default.yml", + "dataset": "error", + "path": "nginx-1.5.0/data_stream/error/elasticsearch/ingest_pipeline/default.yml" + }, + { + "pkgkey": "nginx-1.5.0", + "service": "elasticsearch", + "type": "ingest_pipeline", + "file": "third-party.yml", + "dataset": "error", + "path": "nginx-1.5.0/data_stream/error/elasticsearch/ingest_pipeline/third-party.yml" + } + ] + } + }, + "policy_templates": [ + { + "name": "nginx", + "title": "Nginx logs and metrics", + "description": "Collect logs and metrics from Nginx instances", + "inputs": [ + { + "type": "logfile", + "title": "Collect logs from Nginx instances", + "description": "Collecting Nginx access and error logs" + }, + { + "type": "httpjson", + "vars": [ + { + "name": "url", + "type": "text", + "title": "URL of Splunk Enterprise Server", + "description": "i.e. scheme://host:port, path is automatic", + "multi": false, + "required": true, + "show_user": true, + "default": "https://server.example.com:8089" + }, + { + "name": "username", + "type": "text", + "title": "Splunk REST API Username", + "multi": false, + "required": false, + "show_user": true + }, + { + "name": "password", + "type": "password", + "title": "Splunk REST API Password", + "multi": false, + "required": false, + "show_user": true + }, + { + "name": "token", + "type": "password", + "title": "Splunk Authorization Token", + "description": "Bearer Token or Session Key, e.g. \"Bearer eyJFd3e46...\"\nor \"Splunk 192fd3e...\". Cannot be used with username\nand password.\n", + "multi": false, + "required": false, + "show_user": true + }, + { + "name": "ssl", + "type": "yaml", + "title": "SSL Configuration", + "description": "i.e. certificate_authorities, supported_protocols, verification_mode etc.", + "multi": false, + "required": false, + "show_user": false, + "default": "#certificate_authorities:\n# - |\n# -----BEGIN CERTIFICATE-----\n# MIIDCjCCAfKgAwIBAgITJ706Mu2wJlKckpIvkWxEHvEyijANBgkqhkiG9w0BAQsF\n# ADAUMRIwEAYDVQQDDAlsb2NhbGhvc3QwIBcNMTkwNzIyMTkyOTA0WhgPMjExOTA2\n# MjgxOTI5MDRaMBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEB\n# BQADggEPADCCAQoCggEBANce58Y/JykI58iyOXpxGfw0/gMvF0hUQAcUrSMxEO6n\n# fZRA49b4OV4SwWmA3395uL2eB2NB8y8qdQ9muXUdPBWE4l9rMZ6gmfu90N5B5uEl\n# 94NcfBfYOKi1fJQ9i7WKhTjlRkMCgBkWPkUokvBZFRt8RtF7zI77BSEorHGQCk9t\n# /D7BS0GJyfVEhftbWcFEAG3VRcoMhF7kUzYwp+qESoriFRYLeDWv68ZOvG7eoWnP\n# PsvZStEVEimjvK5NSESEQa9xWyJOmlOKXhkdymtcUd/nXnx6UTCFgnkgzSdTWV41\n# CI6B6aJ9svCTI2QuoIq2HxX/ix7OvW1huVmcyHVxyUECAwEAAaNTMFEwHQYDVR0O\n# BBYEFPwN1OceFGm9v6ux8G+DZ3TUDYxqMB8GA1UdIwQYMBaAFPwN1OceFGm9v6ux\n# 8G+DZ3TUDYxqMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAG5D\n# 874A4YI7YUwOVsVAdbWtgp1d0zKcPRR+r2OdSbTAV5/gcS3jgBJ3i1BN34JuDVFw\n# 3DeJSYT3nxy2Y56lLnxDeF8CUTUtVQx3CuGkRg1ouGAHpO/6OqOhwLLorEmxi7tA\n# H2O8mtT0poX5AnOAhzVy7QW0D/k4WaoLyckM5hUa6RtvgvLxOwA0U+VGurCDoctu\n# 8F4QOgTAWyh8EZIwaKCliFRSynDpv3JTUwtfZkxo6K6nce1RhCWFAsMvDZL8Dgc0\n# yvgJ38BRsFOtkRuAGSf6ZUwTO8JJRRIFnpUzXflAnGivK9M13D5GEQMmIl6U9Pvk\n# sxSmbIUfc2SGJGCJD4I=\n# -----END CERTIFICATE-----\n" + } + ], + "title": "Collect logs from third-party REST API (experimental)", + "description": "Collect logs from third-party REST API (experimental)" + }, + { + "type": "nginx/metrics", + "vars": [ + { + "name": "hosts", + "type": "text", + "title": "Hosts", + "multi": true, + "required": true, + "show_user": true, + "default": ["http://127.0.0.1:80"] + } + ], + "title": "Collect metrics from Nginx instances", + "description": "Collecting Nginx stub status metrics" + } + ], + "multiple": true + } + ], + "data_streams": [ + { + "type": "logs", + "dataset": "nginx.access", + "title": "Nginx access logs", + "release": "ga", + "ingest_pipeline": "default", + "streams": [ + { + "input": "logfile", + "vars": [ + { + "name": "paths", + "type": "text", + "title": "Paths", + "multi": true, + "required": true, + "show_user": true, + "default": ["/var/log/nginx/access.log*"] + }, + { + "name": "tags", + "type": "text", + "title": "Tags", + "multi": true, + "required": true, + "show_user": false, + "default": ["nginx-access"] + }, + { + "name": "preserve_original_event", + "type": "bool", + "title": "Preserve original event", + "description": "Preserves a raw copy of the original event, added to the field `event.original`", + "multi": false, + "required": true, + "show_user": true, + "default": false + }, + { + "name": "processors", + "type": "yaml", + "title": "Processors", + "description": "Processors are used to reduce the number of fields in the exported event or to enhance the event with metadata. This executes in the agent before the logs are parsed. See [Processors](https://www.elastic.co/guide/en/beats/filebeat/current/filtering-and-enhancing-data.html) for details.\n", + "multi": false, + "required": false, + "show_user": false + }, + { + "name": "ignore_older", + "type": "text", + "title": "Ignore events older than", + "description": "If this option is specified, events that are older than the specified amount of time are ignored. Valid time units are \"ns\", \"us\" (or \"µs\"), \"ms\", \"s\", \"m\", \"h\".", + "multi": false, + "required": false, + "show_user": false, + "default": "72h" + } + ], + "template_path": "stream.yml.hbs", + "title": "Nginx access logs", + "description": "Collect Nginx access logs", + "enabled": true + }, + { + "input": "httpjson", + "vars": [ + { + "name": "interval", + "type": "text", + "title": "Interval to query Splunk Enterprise REST API", + "description": "Go Duration syntax (eg. 10s)", + "multi": false, + "required": true, + "show_user": true, + "default": "10s" + }, + { + "name": "search", + "type": "text", + "title": "Splunk search string", + "multi": false, + "required": true, + "show_user": true, + "default": "search sourcetype=nginx:plus:access" + }, + { + "name": "tags", + "type": "text", + "title": "Tags", + "multi": true, + "required": false, + "show_user": false, + "default": ["forwarded", "nginx-access"] + }, + { + "name": "preserve_original_event", + "type": "bool", + "title": "Preserve original event", + "description": "Preserves a raw copy of the original event, added to the field `event.original`", + "multi": false, + "required": true, + "show_user": true, + "default": false + }, + { + "name": "processors", + "type": "yaml", + "title": "Processors", + "description": "Processors are used to reduce the number of fields in the exported event or to enhance the event with metadata. This executes in the agent before the logs are parsed. See [Processors](https://www.elastic.co/guide/en/beats/filebeat/current/filtering-and-enhancing-data.html) for details.", + "multi": false, + "required": false, + "show_user": false + } + ], + "template_path": "httpjson.yml.hbs", + "title": "Nginx access logs via Splunk Enterprise REST API", + "description": "Collect Nginx access logs via Splunk Enterprise REST API", + "enabled": false + } + ], + "package": "nginx", + "path": "access" + }, + { + "type": "logs", + "dataset": "nginx.error", + "title": "Nginx error logs", + "release": "ga", + "ingest_pipeline": "default", + "streams": [ + { + "input": "logfile", + "vars": [ + { + "name": "paths", + "type": "text", + "title": "Paths", + "multi": true, + "required": true, + "show_user": true, + "default": ["/var/log/nginx/error.log*"] + }, + { + "name": "tags", + "type": "text", + "title": "Tags", + "multi": true, + "required": true, + "show_user": false, + "default": ["nginx-error"] + }, + { + "name": "preserve_original_event", + "type": "bool", + "title": "Preserve original event", + "description": "Preserves a raw copy of the original event, added to the field `event.original`", + "multi": false, + "required": true, + "show_user": true, + "default": false + }, + { + "name": "processors", + "type": "yaml", + "title": "Processors", + "description": "Processors are used to reduce the number of fields in the exported event or to enhance the event with metadata. This executes in the agent before the logs are parsed. See [Processors](https://www.elastic.co/guide/en/beats/filebeat/current/filtering-and-enhancing-data.html) for details.\n", + "multi": false, + "required": false, + "show_user": false + }, + { + "name": "ignore_older", + "type": "text", + "title": "Ignore events older than", + "description": "If this option is specified, events that are older than the specified amount of time are ignored. Valid time units are \"ns\", \"us\" (or \"µs\"), \"ms\", \"s\", \"m\", \"h\".", + "multi": false, + "required": false, + "show_user": false, + "default": "72h" + } + ], + "template_path": "stream.yml.hbs", + "title": "Nginx error logs", + "description": "Collect Nginx error logs", + "enabled": true + }, + { + "input": "httpjson", + "vars": [ + { + "name": "interval", + "type": "text", + "title": "Interval to query REST API", + "description": "Go Duration syntax (eg. 10s)", + "multi": false, + "required": true, + "show_user": true, + "default": "10s" + }, + { + "name": "search", + "type": "text", + "title": "Search String", + "multi": false, + "required": true, + "show_user": true, + "default": "search sourcetype=nginx:plus:error" + }, + { + "name": "tags", + "type": "text", + "title": "Tags", + "multi": true, + "required": false, + "show_user": false, + "default": ["forwarded", "nginx-error"] + }, + { + "name": "preserve_original_event", + "type": "bool", + "title": "Preserve original event", + "description": "Preserves a raw copy of the original event, added to the field `event.original`", + "multi": false, + "required": true, + "show_user": true, + "default": false + }, + { + "name": "processors", + "type": "yaml", + "title": "Processors", + "description": "Processors are used to reduce the number of fields in the exported event or to enhance the event with metadata. This executes in the agent before the logs are parsed. See [Processors](https://www.elastic.co/guide/en/beats/filebeat/current/filtering-and-enhancing-data.html) for details.", + "multi": false, + "required": false, + "show_user": false + } + ], + "template_path": "httpjson.yml.hbs", + "title": "Nginx error logs via Splunk REST API", + "description": "Collect Nginx error logs via Splunk REST API", + "enabled": false + } + ], + "package": "nginx", + "path": "error" + }, + { + "type": "metrics", + "dataset": "nginx.stubstatus", + "title": "Nginx stubstatus metrics", + "release": "ga", + "streams": [ + { + "input": "nginx/metrics", + "vars": [ + { + "name": "period", + "type": "text", + "title": "Period", + "multi": false, + "required": true, + "show_user": true, + "default": "10s" + }, + { + "name": "server_status_path", + "type": "text", + "title": "Server Status Path", + "multi": false, + "required": true, + "show_user": false, + "default": "/nginx_status" + } + ], + "template_path": "stream.yml.hbs", + "title": "Nginx stub status metrics", + "description": "Collect Nginx stub status metrics", + "enabled": true + } + ], + "package": "nginx", + "path": "stubstatus" + } + ], + "latestVersion": "1.5.0", + "keepPoliciesUpToDate": false, + "status": "not_installed" +} diff --git a/x-pack/plugins/fleet/server/services/package_policies/simplified_package_policy_helper.test.ts b/x-pack/plugins/fleet/server/services/package_policies/simplified_package_policy_helper.test.ts new file mode 100644 index 00000000000000..15fd7c902b02ea --- /dev/null +++ b/x-pack/plugins/fleet/server/services/package_policies/simplified_package_policy_helper.test.ts @@ -0,0 +1,118 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { NewPackagePolicy, PackageInfo } from '../../types'; + +import { + simplifiedPackagePolicytoNewPackagePolicy, + generateInputId, +} from './simplified_package_policy_helper'; +import nginxPackageInfo from './fixtures/package_info/nginx_1.5.0.json'; + +function getEnabledInputsAndStreams(newPackagePolicy: NewPackagePolicy) { + return newPackagePolicy.inputs + .filter((input) => input.enabled) + .reduce((acc, input) => { + const inputId = generateInputId(input); + + acc[inputId] = input.streams + .filter((stream) => stream.enabled) + .map((stream) => stream.data_stream.dataset); + + return acc; + }, {} as Record); +} + +describe('toPackagePolicy', () => { + describe('With nginx package', () => { + it('should work', () => { + const res = simplifiedPackagePolicytoNewPackagePolicy( + { + name: 'nginx-1', + namespace: 'default', + policy_id: 'policy123', + description: 'Test description', + inputs: { + 'nginx-logfile': { + streams: { + 'nginx.error': { + vars: { + tags: ['test', 'nginx-error'], + }, + }, + }, + }, + 'nginx-nginx/metrics': {}, + }, + }, + nginxPackageInfo as unknown as PackageInfo + ); + + expect(res).toMatchSnapshot(); + }); + + it('should enable default inputs streams', () => { + const res = simplifiedPackagePolicytoNewPackagePolicy( + { + name: 'nginx-1', + namespace: 'default', + policy_id: 'policy123', + description: 'Test description', + }, + nginxPackageInfo as unknown as PackageInfo + ); + + expect(getEnabledInputsAndStreams(res)).toEqual({ + 'nginx-logfile': ['nginx.access', 'nginx.error'], + 'nginx-nginx/metrics': ['nginx.stubstatus'], + }); + }); + + it('should allow user to disable inputs', () => { + const res = simplifiedPackagePolicytoNewPackagePolicy( + { + name: 'nginx-1', + namespace: 'default', + policy_id: 'policy123', + description: 'Test description', + inputs: { + 'nginx-logfile': { enabled: false }, + }, + }, + nginxPackageInfo as unknown as PackageInfo + ); + + expect(getEnabledInputsAndStreams(res)).toEqual({ + 'nginx-nginx/metrics': ['nginx.stubstatus'], + }); + }); + + it('should allow user to disable streams', () => { + const res = simplifiedPackagePolicytoNewPackagePolicy( + { + name: 'nginx-1', + namespace: 'default', + policy_id: 'policy123', + description: 'Test description', + inputs: { + 'nginx-logfile': { + streams: { + 'nginx.error': { enabled: false }, + }, + }, + }, + }, + nginxPackageInfo as unknown as PackageInfo + ); + + expect(getEnabledInputsAndStreams(res)).toEqual({ + 'nginx-logfile': ['nginx.access'], + 'nginx-nginx/metrics': ['nginx.stubstatus'], + }); + }); + }); +}); diff --git a/x-pack/plugins/fleet/server/services/package_policies/simplified_package_policy_helper.ts b/x-pack/plugins/fleet/server/services/package_policies/simplified_package_policy_helper.ts new file mode 100644 index 00000000000000..12db049aef71e5 --- /dev/null +++ b/x-pack/plugins/fleet/server/services/package_policies/simplified_package_policy_helper.ts @@ -0,0 +1,129 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { packageToPackagePolicy } from '../../../common/services'; +import type { + NewPackagePolicyInput, + NewPackagePolicyInputStream, + PackagePolicyConfigRecord, +} from '../../../common/types'; +import { PackagePolicyValidationError } from '../../errors'; +import type { NewPackagePolicy, PackageInfo } from '../../types'; + +type SimplifiedVars = Record; + +export interface SimplifiedPackagePolicy { + id?: string; + policy_id: string; + namespace: string; + name: string; + description?: string; + vars?: SimplifiedVars; + inputs?: Record< + string, + { + enabled?: boolean | undefined; + vars?: SimplifiedVars; + streams?: Record< + string, + { + enabled?: undefined | boolean; + vars?: SimplifiedVars; + } + >; + } + >; +} + +export function generateInputId(input: NewPackagePolicyInput) { + return `${input.policy_template ? `${input.policy_template}-` : ''}${input.type}`; +} + +function assignVariables( + userProvidedVars: SimplifiedVars, + varsRecord?: PackagePolicyConfigRecord, + ctxMessage = '' +) { + Object.entries(userProvidedVars).forEach(([varKey, varValue]) => { + if (!varsRecord || !varsRecord[varKey]) { + throw new PackagePolicyValidationError(`Variable ${ctxMessage}:${varKey} not found`); + } + + varsRecord[varKey].value = varValue; + }); +} + +type StreamsMap = Map; +type InputMap = Map; + +export function simplifiedPackagePolicytoNewPackagePolicy( + data: SimplifiedPackagePolicy, + packageInfo: PackageInfo +): NewPackagePolicy { + const { + policy_id: policyId, + namespace, + name, + description, + inputs = {}, + vars: packageLevelVars, + } = data; + const packagePolicy = packageToPackagePolicy(packageInfo, policyId, namespace, name, description); + + // Build a input and streams Map to easily find package policy stream + const inputMap: InputMap = new Map(); + packagePolicy.inputs.forEach((input) => { + const streamMap: StreamsMap = new Map(); + input.streams.forEach((stream) => { + streamMap.set(stream.data_stream.dataset, stream); + }); + inputMap.set(generateInputId(input), { input, streams: streamMap }); + }); + + if (packageLevelVars) { + assignVariables(packageLevelVars, packagePolicy.vars); + } + + Object.entries(inputs).forEach(([inputId, val]) => { + const { enabled, streams = {}, vars: inputLevelVars } = val; + + const { input: packagePolicyInput, streams: streamsMap } = inputMap.get(inputId) ?? {}; + if (!packagePolicyInput || !streamsMap) { + throw new PackagePolicyValidationError(`Input not found: ${inputId}`); + } + + if (enabled === false) { + packagePolicyInput.enabled = false; + } else { + packagePolicyInput.enabled = true; + } + + if (inputLevelVars) { + assignVariables(inputLevelVars, packagePolicyInput.vars, `${inputId}`); + } + + Object.entries(streams).forEach(([streamId, streamVal]) => { + const { enabled: streamEnabled, vars: streamsLevelVars } = streamVal; + const packagePolicyStream = streamsMap.get(streamId); + if (!packagePolicyStream) { + throw new PackagePolicyValidationError(`Stream not found ${inputId}: ${streamId}`); + } + + if (streamEnabled === false) { + packagePolicyStream.enabled = false; + } else { + packagePolicyStream.enabled = true; + } + + if (streamsLevelVars) { + assignVariables(streamsLevelVars, packagePolicyStream.vars, `${inputId} ${streamId}`); + } + }); + }); + + return packagePolicy; +} diff --git a/x-pack/plugins/fleet/server/types/models/package_policy.ts b/x-pack/plugins/fleet/server/types/models/package_policy.ts index afceb08b3e89ed..5220f18380dd16 100644 --- a/x-pack/plugins/fleet/server/types/models/package_policy.ts +++ b/x-pack/plugins/fleet/server/types/models/package_policy.ts @@ -129,6 +129,51 @@ export const CreatePackagePolicyRequestBodySchema = schema.object({ force: schema.maybe(schema.boolean()), }); +const SimplifiedVarsSchema = schema.recordOf( + schema.string(), + schema.nullable( + schema.oneOf([ + schema.boolean(), + schema.string(), + schema.number(), + schema.arrayOf(schema.string()), + schema.arrayOf(schema.number()), + ]) + ) +); + +export const SimplifiedCreatePackagePolicyRequestBodySchema = schema.object({ + id: schema.maybe(schema.string()), + name: schema.string(), + description: schema.maybe(schema.string()), + policy_id: schema.string(), + namespace: schema.string({ defaultValue: 'default' }), + package: schema.object({ + name: schema.string(), + version: schema.string(), + }), + force: schema.maybe(schema.boolean()), + vars: schema.maybe(SimplifiedVarsSchema), + inputs: schema.maybe( + schema.recordOf( + schema.string(), + schema.object({ + enabled: schema.maybe(schema.boolean()), + vars: schema.maybe(SimplifiedVarsSchema), + streams: schema.maybe( + schema.recordOf( + schema.string(), + schema.object({ + enabled: schema.maybe(schema.boolean()), + vars: schema.maybe(SimplifiedVarsSchema), + }) + ) + ), + }) + ) + ), +}); + export const UpdatePackagePolicyRequestBodySchema = schema.object({ ...CreatePackagePolicyProps, name: schema.maybe(schema.string()), diff --git a/x-pack/plugins/fleet/server/types/rest_spec/package_policy.ts b/x-pack/plugins/fleet/server/types/rest_spec/package_policy.ts index fa7cdce92400b1..0f5542dd7e9bba 100644 --- a/x-pack/plugins/fleet/server/types/rest_spec/package_policy.ts +++ b/x-pack/plugins/fleet/server/types/rest_spec/package_policy.ts @@ -9,6 +9,7 @@ import { schema } from '@kbn/config-schema'; import { CreatePackagePolicyRequestBodySchema, + SimplifiedCreatePackagePolicyRequestBodySchema, UpdatePackagePolicyRequestBodySchema, } from '../models'; @@ -29,12 +30,18 @@ export const GetOnePackagePolicyRequestSchema = { }; export const CreatePackagePolicyRequestSchema = { - body: CreatePackagePolicyRequestBodySchema, + body: schema.oneOf([ + CreatePackagePolicyRequestBodySchema, + SimplifiedCreatePackagePolicyRequestBodySchema, + ]), }; export const UpdatePackagePolicyRequestSchema = { ...GetOnePackagePolicyRequestSchema, - body: UpdatePackagePolicyRequestBodySchema, + body: schema.oneOf([ + UpdatePackagePolicyRequestBodySchema, + SimplifiedCreatePackagePolicyRequestBodySchema, + ]), }; export const DeletePackagePoliciesRequestSchema = { diff --git a/x-pack/plugins/lens/kibana.json b/x-pack/plugins/lens/kibana.json index bff30e66a9bc84..b84353e116f70b 100644 --- a/x-pack/plugins/lens/kibana.json +++ b/x-pack/plugins/lens/kibana.json @@ -46,7 +46,8 @@ "kibanaUtils", "kibanaReact", "embeddable", - "fieldFormats" + "fieldFormats", + "charts" ], "owner": { "name": "Vis Editors", diff --git a/x-pack/plugins/lens/public/app_plugin/app.tsx b/x-pack/plugins/lens/public/app_plugin/app.tsx index e34fedffaf2896..d314c1198fa9f6 100644 --- a/x-pack/plugins/lens/public/app_plugin/app.tsx +++ b/x-pack/plugins/lens/public/app_plugin/app.tsx @@ -31,7 +31,7 @@ import { SaveModalContainer, runSaveLensVisualization } from './save_modal_conta import { LensInspector } from '../lens_inspector_service'; import { getEditPath } from '../../common'; import { isLensEqual } from './lens_document_equality'; -import { IndexPatternServiceAPI, createIndexPatternService } from '../indexpattern_service/service'; +import { IndexPatternServiceAPI, createIndexPatternService } from '../data_views_service/service'; import { replaceIndexpattern } from '../state_management/lens_slice'; export type SaveProps = Omit & { @@ -403,6 +403,7 @@ export function App({ setHeaderActionMenu={setHeaderActionMenu} indicateNoData={indicateNoData} datasourceMap={datasourceMap} + visualizationMap={visualizationMap} title={persistedDoc?.title} lensInspector={lensInspector} currentDoc={currentDoc} diff --git a/x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx b/x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx index a32cc5c4a532b7..6023445d616770 100644 --- a/x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx +++ b/x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx @@ -210,6 +210,7 @@ export const LensTopNavMenu = ({ onAppLeave, redirectToOrigin, datasourceMap, + visualizationMap, title, goBackToOriginatingApp, contextOriginatingApp, @@ -305,6 +306,10 @@ export const LensTopNavMenu = ({ {} ), datasourceStates, + visualizationState: visualization.state, + activeVisualization: visualization.activeId + ? visualizationMap[visualization.activeId] + : undefined, }) ); // Add ad-hoc data views from the Lens state even if they are not used @@ -337,6 +342,8 @@ export const LensTopNavMenu = ({ activeDatasourceId, rejectedIndexPatterns, datasourceMap, + visualizationMap, + visualization, indexPatterns, dataViewsService, dataViews, diff --git a/x-pack/plugins/lens/public/app_plugin/types.ts b/x-pack/plugins/lens/public/app_plugin/types.ts index 52fe1aa98c500d..335400b4cf793d 100644 --- a/x-pack/plugins/lens/public/app_plugin/types.ts +++ b/x-pack/plugins/lens/public/app_plugin/types.ts @@ -52,7 +52,7 @@ import type { import type { LensAttributeService } from '../lens_attribute_service'; import type { LensEmbeddableInput } from '../embeddable/embeddable'; import type { LensInspector } from '../lens_inspector_service'; -import { IndexPatternServiceAPI } from '../indexpattern_service/service'; +import { IndexPatternServiceAPI } from '../data_views_service/service'; import { Document } from '../persistence/saved_object_store'; export interface RedirectToOriginProps { @@ -106,6 +106,7 @@ export interface LensTopNavMenuProps { setIsSaveModalVisible: React.Dispatch>; runSave: RunSave; datasourceMap: DatasourceMap; + visualizationMap: VisualizationMap; title?: string; lensInspector: LensInspector; goBackToOriginatingApp?: () => void; diff --git a/x-pack/plugins/lens/public/indexpattern_service/loader.test.ts b/x-pack/plugins/lens/public/data_views_service/loader.test.ts similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_service/loader.test.ts rename to x-pack/plugins/lens/public/data_views_service/loader.test.ts diff --git a/x-pack/plugins/lens/public/indexpattern_service/loader.ts b/x-pack/plugins/lens/public/data_views_service/loader.ts similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_service/loader.ts rename to x-pack/plugins/lens/public/data_views_service/loader.ts diff --git a/x-pack/plugins/lens/public/indexpattern_service/mocks.ts b/x-pack/plugins/lens/public/data_views_service/mocks.ts similarity index 82% rename from x-pack/plugins/lens/public/indexpattern_service/mocks.ts rename to x-pack/plugins/lens/public/data_views_service/mocks.ts index 048333786fdd6e..55bf80ae60a46e 100644 --- a/x-pack/plugins/lens/public/indexpattern_service/mocks.ts +++ b/x-pack/plugins/lens/public/data_views_service/mocks.ts @@ -11,22 +11,38 @@ import { createMockedIndexPattern, createMockedRestrictedIndexPattern, } from '../indexpattern_datasource/mocks'; -import { IndexPattern } from '../types'; +import { DataViewsState } from '../state_management'; +import { ExistingFieldsMap, IndexPattern } from '../types'; import { getFieldByNameFactory } from './loader'; -export function loadInitialDataViews() { - const indexPattern = createMockedIndexPattern(); - const restricted = createMockedRestrictedIndexPattern(); +/** + * Create a DataViewState from partial parameters, and infer the rest from the passed one. + * Passing no parameter will return an empty state. + */ +export const createMockDataViewsState = ({ + indexPatterns, + indexPatternRefs, + isFirstExistenceFetch, + existingFields, +}: Partial = {}): DataViewsState => { + const refs = + indexPatternRefs ?? + Object.values(indexPatterns ?? {}).map(({ id, title, name }) => ({ id, title, name })); + const allFields = + existingFields ?? + refs.reduce((acc, { id, title }) => { + if (indexPatterns && id in indexPatterns) { + acc[title] = Object.fromEntries(indexPatterns[id].fields.map((f) => [f.displayName, true])); + } + return acc; + }, {} as ExistingFieldsMap); return { - indexPatternRefs: [], - existingFields: {}, - indexPatterns: { - [indexPattern.id]: indexPattern, - [restricted.id]: restricted, - }, - isFirstExistenceFetch: false, + indexPatterns: indexPatterns ?? {}, + indexPatternRefs: refs, + isFirstExistenceFetch: Boolean(isFirstExistenceFetch), + existingFields: allFields, }; -} +}; export const createMockStorage = (lastData?: Record) => { return { diff --git a/x-pack/plugins/lens/public/indexpattern_service/service.ts b/x-pack/plugins/lens/public/data_views_service/service.ts similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_service/service.ts rename to x-pack/plugins/lens/public/data_views_service/service.ts diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/buttons/drop_targets_utils.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/buttons/drop_targets_utils.tsx index 8ce2a4c0cc9750..5f3fd2d4a73b5b 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/buttons/drop_targets_utils.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/buttons/drop_targets_utils.tsx @@ -196,9 +196,9 @@ export interface OnVisDropProps { group?: VisualizationDimensionGroupConfig; } -export function onDropForVisualization( +export function onDropForVisualization( props: OnVisDropProps, - activeVisualization: Visualization + activeVisualization: Visualization ) { const { prevState, target, frame, dropType, source, group } = props; const { layerId, columnId, groupId } = target; diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_container.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_container.tsx index f3cfa9a97667cb..cd74119bbe3156 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_container.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_container.tsx @@ -29,7 +29,8 @@ function fromExcludedClickTarget(event: Event) { ) { if ( node.classList!.contains(DONT_CLOSE_DIMENSION_CONTAINER_ON_CLICK_CLASS) || - node.classList!.contains('euiBody-hasPortalContent') + node.classList!.contains('euiBody-hasPortalContent') || + node.getAttribute('data-euiportal') === 'true' ) { return true; } 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 544835d2e3c21d..65008196c4b8fe 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 @@ -18,7 +18,7 @@ import { EuiIconTip, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { IndexPatternServiceAPI } from '../../../indexpattern_service/service'; +import { IndexPatternServiceAPI } from '../../../data_views_service/service'; import { NativeRenderer } from '../../../native_renderer'; import { StateSetter, @@ -524,8 +524,13 @@ export function LayerPanel( columnId, label: columnLabelMap?.[columnId] ?? '', hideTooltip, - invalid: group.invalid, - invalidMessage: group.invalidMessage, + ...(activeVisualization?.validateColumn?.( + visualizationState, + { dataViews }, + layerId, + columnId, + group + ) || { invalid: false }), })} )} diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/types.ts b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/types.ts index 3e1458d42c438e..c4a2d77c30baba 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/types.ts +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/types.ts @@ -6,7 +6,7 @@ */ import { UiActionsStart } from '@kbn/ui-actions-plugin/public'; -import { IndexPatternServiceAPI } from '../../../indexpattern_service/service'; +import { IndexPatternServiceAPI } from '../../../data_views_service/service'; import { Visualization, diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/data_panel_wrapper.test.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/data_panel_wrapper.test.tsx index 63e4f88d6d2346..9370892a2d7fe6 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/data_panel_wrapper.test.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/data_panel_wrapper.test.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { DataPanelWrapper } from './data_panel_wrapper'; -import { Datasource, DatasourceDataPanelProps } from '../../types'; +import { Datasource, DatasourceDataPanelProps, VisualizationMap } from '../../types'; import { DragDropIdentifier } from '../../drag_drop'; import { UiActionsStart } from '@kbn/ui-actions-plugin/public'; import { createMockFramePublicAPI, mockStoreDeps, mountWithProvider } from '../../mocks'; @@ -26,12 +26,14 @@ describe('Data Panel Wrapper', () => { const datasourceMap = { activeDatasource: { renderDataPanel, + getUsedDataViews: jest.fn(), } as unknown as Datasource, }; const mountResult = await mountWithProvider( {}} core={{} as DatasourceDataPanelProps['core']} dropOntoWorkspace={(field: DragDropIdentifier) => {}} diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/data_panel_wrapper.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/data_panel_wrapper.tsx index 553a61ba2c1c55..0e2b7f88ca6f24 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/data_panel_wrapper.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/data_panel_wrapper.tsx @@ -16,7 +16,13 @@ import { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; import { Easteregg } from './easteregg'; import { NativeRenderer } from '../../native_renderer'; import { DragContext, DragDropIdentifier } from '../../drag_drop'; -import { StateSetter, DatasourceDataPanelProps, DatasourceMap, FramePublicAPI } from '../../types'; +import { + StateSetter, + DatasourceDataPanelProps, + DatasourceMap, + FramePublicAPI, + VisualizationMap, +} from '../../types'; import { switchDatasource, useLensDispatch, @@ -27,14 +33,16 @@ import { selectExecutionContext, selectActiveDatasourceId, selectDatasourceStates, + selectVisualizationState, } from '../../state_management'; import { initializeSources } from './state_helpers'; -import type { IndexPatternServiceAPI } from '../../indexpattern_service/service'; +import type { IndexPatternServiceAPI } from '../../data_views_service/service'; import { changeIndexPattern } from '../../state_management/lens_slice'; import { getInitialDataViewsObject } from '../../utils'; interface DataPanelWrapperProps { datasourceMap: DatasourceMap; + visualizationMap: VisualizationMap; showNoDataPopover: () => void; core: DatasourceDataPanelProps['core']; dropOntoWorkspace: (field: DragDropIdentifier) => void; @@ -48,6 +56,7 @@ export const DataPanelWrapper = memo((props: DataPanelWrapperProps) => { const externalContext = useLensSelector(selectExecutionContext); const activeDatasourceId = useLensSelector(selectActiveDatasourceId); const datasourceStates = useLensSelector(selectDatasourceStates); + const visualizationState = useLensSelector(selectVisualizationState); const datasourceIsLoading = activeDatasourceId ? datasourceStates[activeDatasourceId].isLoading @@ -74,6 +83,8 @@ export const DataPanelWrapper = memo((props: DataPanelWrapperProps) => { initializeSources( { datasourceMap: props.datasourceMap, + visualizationMap: props.visualizationMap, + visualizationState, datasourceStates, dataViews: props.plugins.dataViews, references: undefined, @@ -84,29 +95,38 @@ export const DataPanelWrapper = memo((props: DataPanelWrapperProps) => { { isFullEditor: true, } - ).then(({ states, indexPatterns, indexPatternRefs }) => { - const newDatasourceStates = Object.entries(states).reduce( - (state, [datasourceId, datasourceState]) => ({ - ...state, - [datasourceId]: { - ...datasourceState, - isLoading: false, - }, - }), - {} - ); - dispatchLens( - setState({ - datasourceStates: newDatasourceStates, - dataViews: getInitialDataViewsObject(indexPatterns, indexPatternRefs), - }) - ); - }); + ).then( + ({ + datasourceStates: newDatasourceStates, + visualizationState: newVizState, + indexPatterns, + indexPatternRefs, + }) => { + dispatchLens( + setState({ + visualization: { ...visualizationState, state: newVizState }, + datasourceStates: Object.entries(newDatasourceStates).reduce( + (state, [datasourceId, datasourceState]) => ({ + ...state, + [datasourceId]: { + ...datasourceState, + isLoading: false, + }, + }), + {} + ), + dataViews: getInitialDataViewsObject(indexPatterns, indexPatternRefs), + }) + ); + } + ); } }, [ datasourceStates, + visualizationState, activeDatasourceId, props.datasourceMap, + props.visualizationMap, dispatchLens, props.plugins.dataViews, props.core.uiSettings, @@ -145,6 +165,19 @@ export const DataPanelWrapper = memo((props: DataPanelWrapperProps) => { onChangeIndexPattern, indexPatternService: props.indexPatternService, frame: props.frame, + // Visualization can handle dataViews, so need to pass to the data panel the full list of used dataViews + usedIndexPatterns: [ + ...((activeDatasourceId && + props.datasourceMap[activeDatasourceId]?.getUsedDataViews( + datasourceStates[activeDatasourceId].state + )) || + []), + ...((visualizationState.activeId && + props.visualizationMap[visualizationState.activeId]?.getUsedDataViews?.( + visualizationState.state + )) || + []), + ], }; const [showDatasourceSwitcher, setDatasourceSwitcher] = useState(false); diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.tsx index 090161ee11565e..4100e25da76670 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.tsx @@ -30,7 +30,7 @@ import { } from '../../state_management'; import type { LensInspector } from '../../lens_inspector_service'; import { ErrorBoundary, showMemoizedErrorNotification } from '../../lens_ui_errors'; -import { IndexPatternServiceAPI } from '../../indexpattern_service/service'; +import { IndexPatternServiceAPI } from '../../data_views_service/service'; export interface EditorFrameProps { datasourceMap: DatasourceMap; @@ -120,6 +120,7 @@ export function EditorFrame(props: EditorFrameProps) { core={props.core} plugins={props.plugins} datasourceMap={datasourceMap} + visualizationMap={visualizationMap} showNoDataPopover={props.showNoDataPopover} dropOntoWorkspace={dropOntoWorkspace} hasSuggestionForField={hasSuggestionForField} 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 a5cc6c06644ffd..aab10d783ab520 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 @@ -37,9 +37,9 @@ import { getMissingVisualizationTypeError, getUnknownVisualizationTypeError, } from '../error_helper'; -import type { DatasourceStates, DataViewsState } from '../../state_management'; +import type { DatasourceStates, DataViewsState, VisualizationState } from '../../state_management'; import { readFromStorage } from '../../settings_storage'; -import { loadIndexPatternRefs, loadIndexPatterns } from '../../indexpattern_service/loader'; +import { loadIndexPatternRefs, loadIndexPatterns } from '../../data_views_service/loader'; function getIndexPatterns( references?: SavedObjectReference[], @@ -158,6 +158,8 @@ export async function initializeSources( { dataViews, datasourceMap, + visualizationMap, + visualizationState, datasourceStates, storage, defaultIndexPatternId, @@ -167,6 +169,8 @@ export async function initializeSources( }: { dataViews: DataViewsContract; datasourceMap: DatasourceMap; + visualizationMap: VisualizationMap; + visualizationState: VisualizationState; datasourceStates: DatasourceStates; defaultIndexPatternId: string; storage: IStorageWrapper; @@ -192,7 +196,7 @@ export async function initializeSources( return { indexPatterns, indexPatternRefs, - states: initializeDatasources({ + datasourceStates: initializeDatasources({ datasourceMap, datasourceStates, initialContext, @@ -200,9 +204,34 @@ export async function initializeSources( indexPatterns, references, }), + visualizationState: initializeVisualization({ + visualizationMap, + visualizationState, + references, + }), }; } +export function initializeVisualization({ + visualizationMap, + visualizationState, + references, +}: { + visualizationState: VisualizationState; + visualizationMap: VisualizationMap; + references?: SavedObjectReference[]; +}) { + if (visualizationState?.activeId) { + return ( + visualizationMap[visualizationState.activeId]?.fromPersistableState?.( + visualizationState.state, + references + ) ?? visualizationState.state + ); + } + return visualizationState.state; +} + export function initializeDatasources({ datasourceMap, datasourceStates, @@ -271,7 +300,7 @@ export async function persistedStateToExpression( ): Promise<{ ast: Ast | null; errors: ErrorMessage[] | undefined }> { const { state: { - visualization: visualizationState, + visualization: persistedVisualizationState, datasourceStates: persistedDatasourceStates, adHocDataViews, internalReferences, @@ -294,6 +323,14 @@ export async function persistedStateToExpression( }; } const visualization = visualizations[visualizationType!]; + const visualizationState = initializeVisualization({ + visualizationMap: visualizations, + visualizationState: { + state: persistedVisualizationState, + activeId: visualizationType, + }, + references: [...references, ...(internalReferences || [])], + }); const datasourceStatesFromSO = Object.fromEntries( Object.entries(persistedDatasourceStates).map(([id, state]) => [ id, @@ -404,15 +441,15 @@ export const validateDatasourceAndVisualization = ( currentDatasourceState: unknown | null, currentVisualization: Visualization | null, currentVisualizationState: unknown | undefined, - { datasourceLayers, dataViews }: Pick + frame: Pick ): ErrorMessage[] | undefined => { try { const datasourceValidationErrors = currentDatasourceState - ? currentDataSource?.getErrorMessages(currentDatasourceState, dataViews.indexPatterns) + ? currentDataSource?.getErrorMessages(currentDatasourceState, frame.dataViews.indexPatterns) : undefined; const visualizationValidationErrors = currentVisualizationState - ? currentVisualization?.getErrorMessages(currentVisualizationState, datasourceLayers) + ? currentVisualization?.getErrorMessages(currentVisualizationState, frame) : undefined; if (datasourceValidationErrors?.length || visualizationValidationErrors?.length) { 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 ebe2de3f341d1e..87b34e066f5e5a 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 @@ -243,6 +243,7 @@ export function SuggestionPanel({ visualizationMap[visualizationId], suggestionVisualizationState, { + ...frame, dataViews: frame.dataViews, datasourceLayers: getDatasourceLayers( suggestionDatasourceId diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/warnings_popover.scss b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/warnings_popover.scss index ca1d4b2e2caff7..34829f8323131a 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/warnings_popover.scss +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/warnings_popover.scss @@ -8,6 +8,7 @@ @include euiYScroll; max-height: $euiSize * 20; width: $euiSize * 16; + overflow-wrap: break-word; } .lnsWorkspaceWarningList__item { diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.test.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.test.tsx index cc2397b820a917..257d6d78cff994 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.test.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.test.tsx @@ -562,7 +562,10 @@ describe('workspace_panel', () => { expect(mounted.lensStore.dispatch).toHaveBeenCalledWith({ type: 'lens/onActiveDataChange', - payload: tablesData, + payload: { + activeData: tablesData, + requestWarnings: [], + }, }); }); 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 e2ad7cf809ee7e..5291811671715d 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 @@ -217,22 +217,34 @@ export const InnerWorkspacePanel = React.memo(function InnerWorkspacePanel({ if (renderDeps.current) { const [defaultLayerId] = Object.keys(renderDeps.current.datasourceLayers); + const requestWarnings: string[] = []; + const datasource = Object.values(renderDeps.current?.datasourceMap)[0]; + const datasourceState = Object.values(renderDeps.current?.datasourceStates)[0].state; + if (adapters?.requests) { + plugins.data.search.showWarnings(adapters.requests, (warning) => { + const warningMessage = datasource.getSearchWarningMessages?.(datasourceState, warning); + + requestWarnings.push(...(warningMessage || [])); + if (warningMessage && warningMessage.length) return true; + }); + } if (adapters && adapters.tables) { dispatchLens( - onActiveDataChange( - Object.entries(adapters.tables?.tables).reduce>( + onActiveDataChange({ + activeData: Object.entries(adapters.tables?.tables).reduce>( (acc, [key, value], index, tables) => ({ ...acc, [tables.length === 1 ? defaultLayerId : key]: value, }), {} - ) - ) + ), + requestWarnings, + }) ); } } }, - [dispatchLens] + [dispatchLens, plugins.data.search] ); const shouldApplyExpression = autoApplyEnabled || !initialRenderComplete.current || triggerApply; @@ -606,6 +618,7 @@ export const InnerWorkspacePanel = React.memo(function InnerWorkspacePanel({ datasourceMap={datasourceMap} visualizationMap={visualizationMap} isFullscreen={isFullscreen} + lensInspector={lensInspector} > {renderWorkspace()} @@ -656,6 +669,7 @@ export const VisualizationWrapper = ({ to: context.dateRange.toDate, }, filters: context.filters, + disableShardWarnings: true, }), [context] ); diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel_wrapper.test.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel_wrapper.test.tsx index fcdbedff74a8df..844f3e6cb845e9 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel_wrapper.test.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel_wrapper.test.tsx @@ -18,6 +18,7 @@ import { selectTriggerApplyChanges, } from '../../../state_management'; import { enableAutoApply, setChangesApplied } from '../../../state_management/lens_slice'; +import { LensInspector } from '../../../lens_inspector_service'; describe('workspace_panel_wrapper', () => { let mockVisualization: jest.Mocked; @@ -39,6 +40,7 @@ describe('workspace_panel_wrapper', () => { datasourceMap={{}} datasourceStates={{}} isFullscreen={false} + lensInspector={{} as unknown as LensInspector} > @@ -60,6 +62,7 @@ describe('workspace_panel_wrapper', () => { datasourceMap={{}} datasourceStates={{}} isFullscreen={false} + lensInspector={{} as unknown as LensInspector} /> ); @@ -114,6 +117,7 @@ describe('workspace_panel_wrapper', () => { datasourceMap={{}} datasourceStates={{}} isFullscreen={false} + lensInspector={{} as unknown as LensInspector} >
diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel_wrapper.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel_wrapper.tsx index a10d4c2f4333a1..cdc293dc78bc5e 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel_wrapper.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel_wrapper.tsx @@ -31,8 +31,10 @@ import { selectChangesApplied, applyChanges, selectAutoApplyEnabled, + selectStagedRequestWarnings, } from '../../../state_management'; import { WorkspaceTitle } from './title'; +import { LensInspector } from '../../../lens_inspector_service'; export const AUTO_APPLY_DISABLED_STORAGE_KEY = 'autoApplyDisabled'; @@ -45,6 +47,7 @@ export interface WorkspacePanelWrapperProps { datasourceMap: DatasourceMap; datasourceStates: DatasourceStates; isFullscreen: boolean; + lensInspector: LensInspector; } export function WorkspacePanelWrapper({ @@ -56,11 +59,13 @@ export function WorkspacePanelWrapper({ datasourceMap, datasourceStates, isFullscreen, + lensInspector, }: WorkspacePanelWrapperProps) { const dispatchLens = useLensDispatch(); const changesApplied = useLensSelector(selectChangesApplied); const autoApplyEnabled = useLensSelector(selectAutoApplyEnabled); + const requestWarnings = useLensSelector(selectStagedRequestWarnings); const activeVisualization = visualizationId ? visualizationMap[visualizationId] : null; const setVisualizationState = useCallback( @@ -99,12 +104,18 @@ export function WorkspacePanelWrapper({ const datasource = datasourceMap[datasourceId]; if (!datasourceState.isLoading && datasource.getWarningMessages) { warningMessages.push( - ...(datasource.getWarningMessages(datasourceState.state, framePublicAPI, (updater) => - setDatasourceState(updater, datasourceId) + ...(datasource.getWarningMessages( + datasourceState.state, + framePublicAPI, + lensInspector.adapters, + (updater) => setDatasourceState(updater, datasourceId) ) || []) ); } }); + if (requestWarnings) { + warningMessages.push(...requestWarnings); + } return ( <> {!(isFullscreen && (autoApplyEnabled || warningMessages?.length)) && ( diff --git a/x-pack/plugins/lens/public/embeddable/embeddable.tsx b/x-pack/plugins/lens/public/embeddable/embeddable.tsx index be6706aded4a00..0e4c0594db3c47 100644 --- a/x-pack/plugins/lens/public/embeddable/embeddable.tsx +++ b/x-pack/plugins/lens/public/embeddable/embeddable.tsx @@ -7,6 +7,7 @@ import { isEqual, uniqBy } from 'lodash'; import React from 'react'; +import { css } from '@emotion/react'; import { i18n } from '@kbn/i18n'; import { render, unmountComponentAtNode } from 'react-dom'; import type { DataViewBase, EsQueryConfig, Filter, Query, TimeRange } from '@kbn/es-query'; @@ -44,6 +45,7 @@ import { SelfStyledEmbeddable, FilterableEmbeddable, } from '@kbn/embeddable-plugin/public'; +import { euiThemeVars } from '@kbn/ui-theme'; import { UiActionsStart } from '@kbn/ui-actions-plugin/public'; import type { DataViewsContract, DataView } from '@kbn/data-views-plugin/public'; import type { @@ -54,7 +56,7 @@ import type { ThemeServiceStart, } from '@kbn/core/public'; import type { SpacesPluginStart } from '@kbn/spaces-plugin/public'; -import { BrushTriggerEvent, ClickTriggerEvent } from '@kbn/charts-plugin/public'; +import { BrushTriggerEvent, ClickTriggerEvent, Warnings } from '@kbn/charts-plugin/public'; import { DataViewPersistableStateService } from '@kbn/data-views-plugin/common'; import { getExecutionContextEvents, trackUiCounterEvents } from '../lens_ui_telemetry'; import { Document } from '../persistence'; @@ -79,7 +81,7 @@ import { getLensInspectorService, LensInspector } from '../lens_inspector_servic import { SharingSavedObjectProps, VisualizationDisplayOptions } from '../types'; import { getActiveDatasourceIdFromDoc, getIndexPatternsObjects, inferTimeField } from '../utils'; import { getLayerMetaInfo, combineQueryAndFilters } from '../app_plugin/show_underlying_data'; -import { convertDataViewIntoLensIndexPattern } from '../indexpattern_service/loader'; +import { convertDataViewIntoLensIndexPattern } from '../data_views_service/loader'; export type LensSavedObjectAttributes = Omit; @@ -233,6 +235,7 @@ export class Embeddable private savedVis: Document | undefined; private expression: string | undefined | null; private domNode: HTMLElement | Element | undefined; + private warningDomNode: HTMLElement | Element | undefined; private subscription: Subscription; private isInitialized = false; private errors: ErrorMessage[] | undefined; @@ -497,6 +500,26 @@ export class Embeddable return isDirty; } + private handleWarnings(adapters?: Partial) { + const activeDatasourceId = getActiveDatasourceIdFromDoc(this.savedVis); + if (!activeDatasourceId || !adapters?.requests) return; + const activeDatasource = this.deps.datasourceMap[activeDatasourceId]; + const docDatasourceState = this.savedVis?.state.datasourceStates[activeDatasourceId]; + const warnings: React.ReactNode[] = []; + this.deps.data.search.showWarnings(adapters.requests, (warning) => { + const warningMessage = activeDatasource.getSearchWarningMessages?.( + docDatasourceState, + warning + ); + + warnings.push(...(warningMessage || [])); + if (warningMessage && warningMessage.length) return true; + }); + if (warnings && this.warningDomNode) { + render(, this.warningDomNode); + } + } + private updateActiveData: ExpressionWrapperProps['onData$'] = (data, adapters) => { this.activeDataInfo.activeData = adapters?.tables?.tables; if (this.input.onLoad) { @@ -510,6 +533,8 @@ export class Embeddable loading: false, error: type === 'error' ? error : undefined, }); + + this.handleWarnings(adapters); }; private onRender: ExpressionWrapperProps['onRender$'] = () => { @@ -625,6 +650,19 @@ export class Embeddable }} noPadding={this.visDisplayOptions?.noPadding} /> +
{ + if (el) { + this.warningDomNode = el; + } + }} + /> , domNode ); @@ -665,6 +703,7 @@ export class Embeddable this.savedVis.state.filters, this.savedVis.references ), + disableShardWarnings: true, }; if (this.externalSearchContext.query) { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.test.tsx index 1163e811e4cf85..f3dea6eb9efe92 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.test.tsx @@ -34,7 +34,7 @@ import { createIndexPatternServiceMock } from '../mocks/data_views_service_mock' import { createMockFramePublicAPI } from '../mocks'; import { DataViewsState } from '../state_management'; import { ExistingFieldsMap, FramePublicAPI, IndexPattern } from '../types'; -import { IndexPatternServiceProps } from '../indexpattern_service/service'; +import { IndexPatternServiceProps } from '../data_views_service/service'; import { FieldSpec, DataView } from '@kbn/data-views-plugin/public'; import { UI_SETTINGS } from '@kbn/data-plugin/public'; @@ -408,7 +408,7 @@ describe('IndexPattern Data Panel', () => { stateChanges?: Partial, propChanges?: Partial ) { - const inst = mountWithIntl(); + const inst = mountWithIntl(); await act(async () => { inst.update(); @@ -418,10 +418,10 @@ describe('IndexPattern Data Panel', () => { await act(async () => { inst.setProps({ ...props, - ...((propChanges as object) || {}), + ...(propChanges || {}), state: { ...props.state, - ...((stateChanges as object) || {}), + ...(stateChanges || {}), }, }); inst.update(); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx index 1d46cef70bc9d6..01053dbb49a2ba 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx @@ -16,9 +16,9 @@ import { EuiPopover, EuiCallOut, EuiFormControlLayout, - EuiIcon, EuiFilterButton, EuiScreenReaderOnly, + EuiIcon, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import type { EsQueryConfig, Query, Filter } from '@kbn/es-query'; @@ -47,7 +47,7 @@ import { LensFieldIcon } from '../shared_components/field_picker/lens_field_icon import { getFieldType } from './pure_utils'; import { FieldGroups, FieldList } from './field_list'; import { fieldContainsData, fieldExists } from '../shared_components'; -import { IndexPatternServiceAPI } from '../indexpattern_service/service'; +import { IndexPatternServiceAPI } from '../data_views_service/service'; export type Props = Omit< DatasourceDataPanelProps, @@ -143,15 +143,16 @@ export function IndexPatternDataPanel({ indexPatternService, frame, onIndexPatternRefresh, + usedIndexPatterns, }: Props) { const { indexPatterns, indexPatternRefs, existingFields, isFirstExistenceFetch } = frame.dataViews; const { currentIndexPatternId } = state; const indexPatternList = uniq( - Object.values(state.layers) - .map((l) => l.indexPatternId) - .concat(currentIndexPatternId) + ( + usedIndexPatterns ?? Object.values(state.layers).map(({ indexPatternId }) => indexPatternId) + ).concat(currentIndexPatternId) ) .filter((id) => !!indexPatterns[id]) .sort() @@ -283,7 +284,7 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({ onIndexPatternRefresh, }: Omit< DatasourceDataPanelProps, - 'state' | 'setState' | 'showNoDataPopover' | 'core' | 'onChangeIndexPattern' + 'state' | 'setState' | 'showNoDataPopover' | 'core' | 'onChangeIndexPattern' | 'usedIndexPatterns' > & { data: DataPublicPluginStart; dataViews: DataViewsPublicPluginStart; 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 56acffaed1ffb4..3f7c4f1e9b006c 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 @@ -55,8 +55,8 @@ jest.mock('./reference_editor', () => ({ ReferenceEditor: () => null, })); jest.mock('../loader'); -jest.mock('../query_input', () => ({ - QueryInput: () => null, +jest.mock('@kbn/unified-search-plugin/public', () => ({ + QueryStringInput: () => null, })); jest.mock('../operations'); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/filtering.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/filtering.tsx index 5117e935c59d62..1c68844079fa63 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/filtering.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/filtering.tsx @@ -19,10 +19,8 @@ import { } from '@elastic/eui'; import type { Query } from '@kbn/es-query'; import { GenericIndexPatternColumn, operationDefinitionMap } from '../operations'; -import { validateQuery } from '../operations/definitions/filters'; -import { QueryInput } from '../query_input'; import type { IndexPatternLayer } from '../types'; -import { useDebouncedValue } from '../../shared_components'; +import { QueryInput, useDebouncedValue, validateQuery } from '../../shared_components'; import type { IndexPattern } from '../../types'; const filterByLabel = i18n.translate('xpack.lens.indexPattern.filterBy.label', { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.test.ts b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.test.ts index e91aa1b286bec3..66c554d7bbe9a2 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.test.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.test.ts @@ -2543,7 +2543,12 @@ describe('IndexPattern Data Source', () => { ); it('should return mismatched time shifts', () => { - const warnings = indexPatternDatasource.getWarningMessages!(state, framePublicAPI, () => {}); + const warnings = indexPatternDatasource.getWarningMessages!( + state, + framePublicAPI, + {}, + () => {} + ); expect(extractTranslationIdsFromWarnings(warnings)).toMatchInlineSnapshot(` Array [ @@ -2556,7 +2561,12 @@ describe('IndexPattern Data Source', () => { it('should show different types of warning messages', () => { framePublicAPI.activeData!.first.columns[1].meta.sourceParams!.hasPrecisionError = true; - const warnings = indexPatternDatasource.getWarningMessages!(state, framePublicAPI, () => {}); + const warnings = indexPatternDatasource.getWarningMessages!( + state, + framePublicAPI, + {}, + () => {} + ); expect(extractTranslationIdsFromWarnings(warnings)).toMatchInlineSnapshot(` Array [ diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.tsx index c806eb525da371..da317d5ea04bea 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.tsx @@ -61,7 +61,12 @@ import { getDatasourceSuggestionsForVisualizeCharts, } from './indexpattern_suggestions'; -import { getFiltersInLayer, getVisualDefaultsForLayer, isColumnInvalid } from './utils'; +import { + getFiltersInLayer, + getTSDBRollupWarningMessages, + getVisualDefaultsForLayer, + isColumnInvalid, +} from './utils'; import { normalizeOperationDataType, isDraggedField } from './pure_utils'; import { LayerPanel } from './layerpanel'; import { @@ -105,6 +110,9 @@ export function columnToOperation( ? 'version' : undefined, hasTimeShift: Boolean(timeShift), + interval: isColumnOfType('date_histogram', column) + ? column.params.interval + : undefined, }; } @@ -653,7 +661,7 @@ export function getIndexPatternDatasource({ }); return messages.length ? messages : undefined; }, - getWarningMessages: (state, frame, setState) => { + getWarningMessages: (state, frame, adapters, setState) => { return [ ...(getStateTimeShiftWarningMessages(data.datatableUtilities, state, frame) || []), ...getPrecisionErrorWarningMessages( @@ -665,6 +673,9 @@ export function getIndexPatternDatasource({ ), ]; }, + getSearchWarningMessages: (state, warning) => { + return [...getTSDBRollupWarningMessages(state, warning)]; + }, getDeprecationMessages: () => { const deprecatedMessages: React.ReactNode[] = []; const useFieldExistenceSamplingKey = 'lens:useFieldExistenceSampling'; @@ -743,6 +754,9 @@ export function getIndexPatternDatasource({ getUsedDataView: (state: IndexPatternPrivateState, layerId: string) => { return state.layers[layerId].indexPatternId; }, + getUsedDataViews: (state) => { + return Object.values(state.layers).map(({ indexPatternId }) => indexPatternId); + }, }; return indexPatternDatasource; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.test.tsx index e90ed2c781d5a2..3950f9a02dadf2 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.test.tsx @@ -2214,6 +2214,7 @@ describe('IndexPattern Data Source suggestions', () => { scale: 'interval', isStaticValue: false, hasTimeShift: false, + interval: 'auto', }, }, { @@ -2225,6 +2226,7 @@ describe('IndexPattern Data Source suggestions', () => { scale: 'ratio', isStaticValue: false, hasTimeShift: false, + interval: undefined, }, }, ], @@ -2289,6 +2291,7 @@ describe('IndexPattern Data Source suggestions', () => { scale: 'ordinal', isStaticValue: false, hasTimeShift: false, + interval: undefined, }, }, { @@ -2300,6 +2303,7 @@ describe('IndexPattern Data Source suggestions', () => { scale: 'interval', isStaticValue: false, hasTimeShift: false, + interval: 'auto', }, }, { @@ -2311,6 +2315,7 @@ describe('IndexPattern Data Source suggestions', () => { scale: 'ratio', isStaticValue: false, hasTimeShift: false, + interval: undefined, }, }, ], @@ -2396,6 +2401,7 @@ describe('IndexPattern Data Source suggestions', () => { scale: 'ordinal', isStaticValue: false, hasTimeShift: false, + interval: undefined, }, }, { @@ -2407,6 +2413,7 @@ describe('IndexPattern Data Source suggestions', () => { scale: 'interval', isStaticValue: false, hasTimeShift: false, + interval: 'auto', }, }, { @@ -2418,6 +2425,7 @@ describe('IndexPattern Data Source suggestions', () => { scale: 'ratio', isStaticValue: false, hasTimeShift: false, + interval: undefined, }, }, ], @@ -2526,6 +2534,7 @@ describe('IndexPattern Data Source suggestions', () => { scale: 'ordinal', isStaticValue: false, hasTimeShift: false, + interval: undefined, }, }, { @@ -2537,6 +2546,7 @@ describe('IndexPattern Data Source suggestions', () => { scale: 'interval', isStaticValue: false, hasTimeShift: false, + interval: 'auto', }, }, { @@ -2548,6 +2558,7 @@ describe('IndexPattern Data Source suggestions', () => { scale: undefined, isStaticValue: false, hasTimeShift: false, + interval: undefined, }, }, ], @@ -3126,6 +3137,7 @@ describe('IndexPattern Data Source suggestions', () => { scale: 'interval', isStaticValue: false, hasTimeShift: false, + interval: 'auto', }, }, { @@ -3137,6 +3149,7 @@ describe('IndexPattern Data Source suggestions', () => { scale: undefined, isStaticValue: false, hasTimeShift: false, + interval: undefined, }, }, { @@ -3148,6 +3161,7 @@ describe('IndexPattern Data Source suggestions', () => { scale: undefined, isStaticValue: false, hasTimeShift: false, + interval: undefined, }, }, ], @@ -3213,6 +3227,7 @@ describe('IndexPattern Data Source suggestions', () => { scale: undefined, isStaticValue: false, hasTimeShift: false, + interval: 'auto', }, }, { @@ -3224,6 +3239,7 @@ describe('IndexPattern Data Source suggestions', () => { scale: undefined, isStaticValue: false, hasTimeShift: false, + interval: undefined, }, }, { @@ -3235,6 +3251,7 @@ describe('IndexPattern Data Source suggestions', () => { scale: undefined, isStaticValue: false, hasTimeShift: false, + interval: undefined, }, }, ], diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/loader.test.ts b/x-pack/plugins/lens/public/indexpattern_datasource/loader.test.ts index 80f6eaecd3a8a7..3d641ca004a3b5 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/loader.test.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/loader.test.ts @@ -14,7 +14,7 @@ import { } from './loader'; import { IndexPatternPersistedState, IndexPatternPrivateState } from './types'; import { DateHistogramIndexPatternColumn, TermsIndexPatternColumn } from './operations'; -import { sampleIndexPatterns } from '../indexpattern_service/mocks'; +import { sampleIndexPatterns } from '../data_views_service/mocks'; const createMockStorage = (lastData?: Record) => { return { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filter_popover.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filter_popover.test.tsx index 0fc67aca367475..475761c94ec54b 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filter_popover.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filter_popover.test.tsx @@ -12,8 +12,8 @@ import { EuiPopover, EuiLink } from '@elastic/eui'; import { createMockedIndexPattern } from '../../../mocks'; import { FilterPopover } from './filter_popover'; import { LabelInput } from '../shared_components'; -import { QueryInput } from '../../../query_input'; import { QueryStringInput } from '@kbn/unified-search-plugin/public'; +import { QueryInput } from '../../../../shared_components'; jest.mock('.', () => ({ isQueryValid: () => true, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filter_popover.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filter_popover.tsx index 95021dd22900ff..17314bbc991c01 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filter_popover.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filter_popover.tsx @@ -10,10 +10,12 @@ import './filter_popover.scss'; import React from 'react'; import { EuiPopover, EuiSpacer } from '@elastic/eui'; import type { Query } from '@kbn/es-query'; +// Need to keep it separate to make it work Jest mocks in dimension_panel tests +// import { QueryInput } from '../../../../shared_components/query_input'; +import { isQueryValid, QueryInput } from '../../../../shared_components'; import { IndexPattern } from '../../../../types'; -import { FilterValue, defaultLabel, isQueryValid } from '.'; +import { FilterValue, defaultLabel } from '.'; import { LabelInput } from '../shared_components'; -import { QueryInput } from '../../../query_input'; export const FilterPopover = ({ filter, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filters.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filters.tsx index cee188b6f483ab..8aff5ac3f850ae 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filters.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filters.tsx @@ -7,7 +7,6 @@ import './filters.scss'; import React, { useState } from 'react'; -import { fromKueryExpression, luceneStringToDsl, toElasticsearchQuery } from '@kbn/es-query'; import { omit } from 'lodash'; import { i18n } from '@kbn/i18n'; import { EuiFormRow, EuiLink, htmlIdGenerator } from '@elastic/eui'; @@ -15,12 +14,17 @@ import type { Query } from '@kbn/es-query'; import type { AggFunctionsMapping } from '@kbn/data-plugin/public'; import { queryFilterToAst } from '@kbn/data-plugin/common'; import { buildExpressionFunction } from '@kbn/expressions-plugin/public'; +import { + DragDropBuckets, + DraggableBucketContainer, + isQueryValid, + NewBucketButton, +} from '../../../../shared_components'; import { IndexPattern } from '../../../../types'; import { updateColumnParam } from '../../layer_helpers'; import type { OperationDefinition } from '..'; import type { BaseIndexPatternColumn } from '../column_types'; import { FilterPopover } from './filter_popover'; -import { DragDropBuckets, DraggableBucketContainer, NewBucketButton } from '../shared_components'; const generateId = htmlIdGenerator(); const OPERATION_NAME = 'filters'; @@ -54,29 +58,6 @@ const defaultFilter: Filter = { label: '', }; -export const validateQuery = (input: Query | undefined, indexPattern: IndexPattern) => { - let isValid = true; - let error: string | undefined; - - try { - if (input) { - if (input.language === 'kuery') { - toElasticsearchQuery(fromKueryExpression(input.query), indexPattern); - } else { - luceneStringToDsl(input.query); - } - } - } catch (e) { - isValid = false; - error = e.message; - } - - return { isValid, error }; -}; - -export const isQueryValid = (input: Query, indexPattern: IndexPattern) => - validateQuery(input, indexPattern).isValid; - export interface FiltersIndexPatternColumn extends BaseIndexPatternColumn { operationType: typeof OPERATION_NAME; params: { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula_public_api.test.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula_public_api.test.ts index 3286696308d51d..c854595757a0ce 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula_public_api.test.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula_public_api.test.ts @@ -10,13 +10,13 @@ import { createFormulaPublicApi, FormulaPublicApi } from './formula_public_api'; import type { DataView } from '@kbn/data-views-plugin/public'; import type { DateHistogramIndexPatternColumn, PersistedIndexPatternLayer } from '../../../types'; -import { convertDataViewIntoLensIndexPattern } from '../../../../indexpattern_service/loader'; +import { convertDataViewIntoLensIndexPattern } from '../../../../data_views_service/loader'; jest.mock('./parse', () => ({ insertOrReplaceFormulaColumn: jest.fn().mockReturnValue({}), })); -jest.mock('../../../../indexpattern_service/loader', () => ({ +jest.mock('../../../../data_views_service/loader', () => ({ convertDataViewIntoLensIndexPattern: jest.fn((v) => v), })); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula_public_api.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula_public_api.ts index f5080de84d67d7..4085ec931d3a6d 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula_public_api.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula_public_api.ts @@ -6,7 +6,7 @@ */ import type { DataView } from '@kbn/data-views-plugin/public'; -import { convertDataViewIntoLensIndexPattern } from '../../../../indexpattern_service/loader'; +import { convertDataViewIntoLensIndexPattern } from '../../../../data_views_service/loader'; import type { IndexPattern } from '../../../../types'; import type { PersistedIndexPatternLayer } from '../../../types'; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/advanced_editor.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/advanced_editor.tsx index 60d5a76a3085e5..9afd9311f026c6 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/advanced_editor.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/advanced_editor.tsx @@ -23,15 +23,15 @@ import { keys, } from '@elastic/eui'; import { IFieldFormat } from '@kbn/field-formats-plugin/common'; -import { useDebounceWithOptions } from '../../../../shared_components'; -import { RangeTypeLens, isValidRange } from './ranges'; -import { FROM_PLACEHOLDER, TO_PLACEHOLDER, TYPING_DEBOUNCE_TIME } from './constants'; import { - NewBucketButton, DragDropBuckets, DraggableBucketContainer, - LabelInput, -} from '../shared_components'; + NewBucketButton, + useDebounceWithOptions, +} from '../../../../shared_components'; +import { RangeTypeLens, isValidRange } from './ranges'; +import { FROM_PLACEHOLDER, TO_PLACEHOLDER, TYPING_DEBOUNCE_TIME } from './constants'; +import { LabelInput } from '../shared_components'; import { isValidNumber } from '../helpers'; const generateId = htmlIdGenerator(); 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 43603d94154d49..bee30a2e0400fb 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 @@ -26,7 +26,7 @@ import { SLICES, } from './constants'; import { RangePopover } from './advanced_editor'; -import { DragDropBuckets } from '../shared_components'; +import { DragDropBuckets } from '../../../../shared_components'; import { getFieldByNameFactory } from '../../../pure_helpers'; import { IndexPattern } from '../../../../types'; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/shared_components/index.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/shared_components/index.tsx index 1dbd20d8767d07..e9e7dba840291d 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/shared_components/index.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/shared_components/index.tsx @@ -4,6 +4,5 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -export * from './buckets'; export * from './label_input'; export * from './form_row'; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/field_inputs.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/field_inputs.tsx index 5ae10751e64c46..f140fdb9807ac6 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/field_inputs.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/field_inputs.tsx @@ -18,12 +18,16 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { ExistingFieldsMap, IndexPattern } from '../../../../types'; -import { TooltipWrapper, useDebouncedValue } from '../../../../shared_components'; +import { + DragDropBuckets, + NewBucketButton, + TooltipWrapper, + useDebouncedValue, +} from '../../../../shared_components'; import { FieldSelect } from '../../../dimension_panel/field_select'; import type { TermsIndexPatternColumn } from './types'; import type { OperationSupportMatrix } from '../../../dimension_panel'; import { supportedTypes } from './constants'; -import { DragDropBuckets, NewBucketButton } from '../shared_components'; const generateId = htmlIdGenerator(); export const MAX_MULTI_FIELDS_SIZE = 3; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/utils.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/utils.tsx index 0f485d71a7f355..ce2f5edad12c5e 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/utils.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/utils.tsx @@ -14,10 +14,15 @@ import { TimeRange } from '@kbn/es-query'; import { EuiLink, EuiTextColor, EuiButton, EuiSpacer } from '@elastic/eui'; import type { DatatableColumn } from '@kbn/expressions-plugin/common'; -import { groupBy, escape } from 'lodash'; +import { groupBy, escape, uniq } from 'lodash'; import type { Query } from '@kbn/data-plugin/common'; +import { SearchResponseWarning } from '@kbn/data-plugin/public/search/types'; import type { FramePublicAPI, IndexPattern, StateSetter } from '../types'; -import type { IndexPatternLayer, IndexPatternPrivateState } from './types'; +import type { + IndexPatternLayer, + IndexPatternPersistedState, + IndexPatternPrivateState, +} from './types'; import type { ReferenceBasedIndexPatternColumn } from './operations/definitions/column_types'; import { @@ -33,12 +38,13 @@ import { } from './operations'; import { getInvalidFieldMessage, isColumnOfType } from './operations/definitions/helpers'; -import { FiltersIndexPatternColumn, isQueryValid } from './operations/definitions/filters'; +import { FiltersIndexPatternColumn } from './operations/definitions/filters'; import { hasField } from './pure_utils'; import { mergeLayer } from './state_helpers'; import { supportsRarityRanking } from './operations/definitions/terms'; import { DEFAULT_MAX_DOC_COUNT } from './operations/definitions/terms/constants'; import { getOriginalId } from '../../common/expressions'; +import { isQueryValid } from '../shared_components'; export function isColumnInvalid( layer: IndexPatternLayer, @@ -159,6 +165,46 @@ const accuracyModeEnabledWarning = (columnName: string, docLink: string) => ( /> ); +export function getTSDBRollupWarningMessages( + state: IndexPatternPersistedState, + warning: SearchResponseWarning +) { + if (state) { + const hasTSDBRollupWarnings = + warning.type === 'shard_failure' && + warning.reason.type === 'unsupported_aggregation_on_downsampled_index'; + if (!hasTSDBRollupWarnings) { + return []; + } + return Object.values(state.layers).flatMap((layer) => + uniq( + Object.values(layer.columns) + .filter((col) => + [ + 'median', + 'percentile', + 'percentile_rank', + 'last_value', + 'unique_count', + 'standard_deviation', + ].includes(col.operationType) + ) + .map((col) => col.label) + ).map((label) => + i18n.translate('xpack.lens.indexPattern.tsdbRollupWarning', { + defaultMessage: + '"{label}" does not work for all indices in the selected data view because it\'s using a function which is not supported on rolled up data. Please edit the visualization to use another function or change the time range.', + values: { + label, + }, + }) + ) + ); + } + + return []; +} + export function getPrecisionErrorWarningMessages( datatableUtilities: DatatableUtilitiesService, state: IndexPatternPrivateState, diff --git a/x-pack/plugins/lens/public/mocks/data_plugin_mock.ts b/x-pack/plugins/lens/public/mocks/data_plugin_mock.ts index 8260c71b04981a..161f14359d5881 100644 --- a/x-pack/plugins/lens/public/mocks/data_plugin_mock.ts +++ b/x-pack/plugins/lens/public/mocks/data_plugin_mock.ts @@ -59,6 +59,7 @@ export function mockDataPlugin( getSessionId: jest.fn(() => currentSessionId), getSession$: jest.fn(() => sessionIdSubject.asObservable()), }, + showWarnings: jest.fn(), }; } diff --git a/x-pack/plugins/lens/public/mocks/data_views_service_mock.ts b/x-pack/plugins/lens/public/mocks/data_views_service_mock.ts index 58a2e102bc3e1b..2846e46a27d6c9 100644 --- a/x-pack/plugins/lens/public/mocks/data_views_service_mock.ts +++ b/x-pack/plugins/lens/public/mocks/data_views_service_mock.ts @@ -13,7 +13,7 @@ import { createIndexPatternService, IndexPatternServiceProps, IndexPatternServiceAPI, -} from '../indexpattern_service/service'; +} from '../data_views_service/service'; export function createIndexPatternServiceMock({ core = coreMock.createStart(), diff --git a/x-pack/plugins/lens/public/mocks/datasource_mock.ts b/x-pack/plugins/lens/public/mocks/datasource_mock.ts index 8111270cc5d124..eec1d062131e74 100644 --- a/x-pack/plugins/lens/public/mocks/datasource_mock.ts +++ b/x-pack/plugins/lens/public/mocks/datasource_mock.ts @@ -61,6 +61,7 @@ export function createMockDatasource(id: string): DatasourceMock { isValidColumn: jest.fn(), isEqual: jest.fn(), getUsedDataView: jest.fn(), + getUsedDataViews: jest.fn(), onRefreshIndexPattern: jest.fn(), }; } diff --git a/x-pack/plugins/lens/public/mocks/index.ts b/x-pack/plugins/lens/public/mocks/index.ts index 0d90e719ebadee..4cfdfbad661af0 100644 --- a/x-pack/plugins/lens/public/mocks/index.ts +++ b/x-pack/plugins/lens/public/mocks/index.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { createMockDataViewsState } from '../data_views_service/mocks'; import { FramePublicAPI, FrameDatasourceAPI } from '../types'; export { mockDataPlugin } from './data_plugin_mock'; export { @@ -29,28 +30,36 @@ export { lensPluginMock } from './lens_plugin_mock'; export type FrameMock = jest.Mocked; -export const createMockFramePublicAPI = (): FrameMock => ({ - datasourceLayers: {}, - dateRange: { fromDate: '2022-03-17T08:25:00.000Z', toDate: '2022-04-17T08:25:00.000Z' }, - dataViews: { - indexPatterns: {}, - indexPatternRefs: [], - isFirstExistenceFetch: true, - existingFields: {}, +export const createMockFramePublicAPI = ({ + datasourceLayers, + dateRange, + dataViews, + activeData, +}: Partial = {}): FrameMock => ({ + datasourceLayers: datasourceLayers ?? {}, + dateRange: dateRange ?? { + fromDate: '2022-03-17T08:25:00.000Z', + toDate: '2022-04-17T08:25:00.000Z', }, + dataViews: createMockDataViewsState(dataViews), + activeData, }); export type FrameDatasourceMock = jest.Mocked; -export const createMockFrameDatasourceAPI = (): FrameDatasourceMock => ({ - datasourceLayers: {}, - dateRange: { fromDate: '2022-03-17T08:25:00.000Z', toDate: '2022-04-17T08:25:00.000Z' }, - query: { query: '', language: 'lucene' }, - filters: [], - dataViews: { - indexPatterns: {}, - indexPatternRefs: [], - isFirstExistenceFetch: true, - existingFields: {}, +export const createMockFrameDatasourceAPI = ({ + datasourceLayers, + dateRange, + dataViews, + query, + filters, +}: Partial = {}): FrameDatasourceMock => ({ + datasourceLayers: datasourceLayers ?? {}, + dateRange: dateRange ?? { + fromDate: '2022-03-17T08:25:00.000Z', + toDate: '2022-04-17T08:25:00.000Z', }, + query: query ?? { query: '', language: 'lucene' }, + filters: filters ?? [], + dataViews: createMockDataViewsState(dataViews), }); diff --git a/x-pack/plugins/lens/public/mocks/store_mocks.tsx b/x-pack/plugins/lens/public/mocks/store_mocks.tsx index e63a79693cadb5..8320f429e9d5a9 100644 --- a/x-pack/plugins/lens/public/mocks/store_mocks.tsx +++ b/x-pack/plugins/lens/public/mocks/store_mocks.tsx @@ -6,9 +6,7 @@ */ import React from 'react'; -// eslint-disable-next-line import/no-extraneous-dependencies import { ReactWrapper } from 'enzyme'; -// eslint-disable-next-line import/no-extraneous-dependencies import { mountWithIntl as mount } from '@kbn/test-jest-helpers'; import { Provider } from 'react-redux'; import { act } from 'react-dom/test-utils'; diff --git a/x-pack/plugins/lens/public/mocks/visualization_mock.ts b/x-pack/plugins/lens/public/mocks/visualization_mock.ts index f002af43f88c8e..23700094dc7c6f 100644 --- a/x-pack/plugins/lens/public/mocks/visualization_mock.ts +++ b/x-pack/plugins/lens/public/mocks/visualization_mock.ts @@ -11,7 +11,7 @@ import { Visualization, VisualizationMap } from '../types'; export function createMockVisualization(id = 'testVis'): jest.Mocked { return { id, - clearLayer: jest.fn((state, _layerId) => state), + clearLayer: jest.fn((state, _layerId, _indexPatternId) => state), removeLayer: jest.fn(), getLayerIds: jest.fn((_state) => ['layer1']), getSupportedLayers: jest.fn(() => [{ type: layerTypes.DATA, label: 'Data Layer' }]), diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/shared_components/buckets.test.tsx b/x-pack/plugins/lens/public/shared_components/drag_drop_bucket/buckets.test.tsx similarity index 97% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/shared_components/buckets.test.tsx rename to x-pack/plugins/lens/public/shared_components/drag_drop_bucket/buckets.test.tsx index 101eca3ab1785e..aba0cbfc40a6e5 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/shared_components/buckets.test.tsx +++ b/x-pack/plugins/lens/public/shared_components/drag_drop_bucket/buckets.test.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { mount, shallow } from 'enzyme'; import { act } from 'react-dom/test-utils'; import { EuiIcon } from '@elastic/eui'; -import { DragDropBuckets, DraggableBucketContainer } from '.'; +import { DragDropBuckets, DraggableBucketContainer } from './buckets'; jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/shared_components/buckets.tsx b/x-pack/plugins/lens/public/shared_components/drag_drop_bucket/buckets.tsx similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/shared_components/buckets.tsx rename to x-pack/plugins/lens/public/shared_components/drag_drop_bucket/buckets.tsx diff --git a/x-pack/plugins/lens/public/shared_components/index.ts b/x-pack/plugins/lens/public/shared_components/index.ts index c22f071ceede3e..924f678c1f96b5 100644 --- a/x-pack/plugins/lens/public/shared_components/index.ts +++ b/x-pack/plugins/lens/public/shared_components/index.ts @@ -12,6 +12,12 @@ export { PalettePicker } from './palette_picker'; export { FieldPicker, LensFieldIcon, TruncatedLabel } from './field_picker'; export type { FieldOption, FieldOptionValue } from './field_picker'; export { ChangeIndexPattern, fieldExists, fieldContainsData } from './dataview_picker'; +export { QueryInput, isQueryValid, validateQuery } from './query_input'; +export { + NewBucketButton, + DraggableBucketContainer, + DragDropBuckets, +} from './drag_drop_bucket/buckets'; export { RangeInputField } from './range_input_field'; export { BucketAxisBoundsControl, diff --git a/x-pack/plugins/lens/public/shared_components/query_input/helpers.ts b/x-pack/plugins/lens/public/shared_components/query_input/helpers.ts new file mode 100644 index 00000000000000..1b598a10f6f508 --- /dev/null +++ b/x-pack/plugins/lens/public/shared_components/query_input/helpers.ts @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { Query } from '@kbn/es-query'; +import { toElasticsearchQuery, fromKueryExpression, luceneStringToDsl } from '@kbn/es-query'; +import { IndexPattern } from '../../types'; + +export const validateQuery = (input: Query | undefined, indexPattern: IndexPattern) => { + let isValid = true; + let error: string | undefined; + + try { + if (input) { + if (input.language === 'kuery') { + toElasticsearchQuery(fromKueryExpression(input.query), indexPattern); + } else { + luceneStringToDsl(input.query); + } + } + } catch (e) { + isValid = false; + error = e.message; + } + + return { isValid, error }; +}; + +export const isQueryValid = (input: Query, indexPattern: IndexPattern) => + validateQuery(input, indexPattern).isValid; diff --git a/x-pack/plugins/lens/public/shared_components/query_input/index.ts b/x-pack/plugins/lens/public/shared_components/query_input/index.ts new file mode 100644 index 00000000000000..b2934de9168228 --- /dev/null +++ b/x-pack/plugins/lens/public/shared_components/query_input/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { QueryInput } from './query_input'; +export { validateQuery, isQueryValid } from './helpers'; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/query_input.tsx b/x-pack/plugins/lens/public/shared_components/query_input/query_input.tsx similarity index 97% rename from x-pack/plugins/lens/public/indexpattern_datasource/query_input.tsx rename to x-pack/plugins/lens/public/shared_components/query_input/query_input.tsx index 583f6b28996c9d..ecbc102eb751cf 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/query_input.tsx +++ b/x-pack/plugins/lens/public/shared_components/query_input/query_input.tsx @@ -10,7 +10,7 @@ import { i18n } from '@kbn/i18n'; import { isEqual } from 'lodash'; import type { Query } from '@kbn/es-query'; import { QueryStringInput } from '@kbn/unified-search-plugin/public'; -import { useDebouncedValue } from '../shared_components'; +import { useDebouncedValue } from '../debounced_value'; export const QueryInput = ({ value, diff --git a/x-pack/plugins/lens/public/state_management/init_middleware/load_initial.ts b/x-pack/plugins/lens/public/state_management/init_middleware/load_initial.ts index 0a000f75ee0065..dc2425917bad8e 100644 --- a/x-pack/plugins/lens/public/state_management/init_middleware/load_initial.ts +++ b/x-pack/plugins/lens/public/state_management/init_middleware/load_initial.ts @@ -97,7 +97,13 @@ export function loadInitial( }, autoApplyDisabled: boolean ) { - const { lensServices, datasourceMap, embeddableEditorIncomingState, initialContext } = storeDeps; + const { + lensServices, + datasourceMap, + embeddableEditorIncomingState, + initialContext, + visualizationMap, + } = storeDeps; const { resolvedDateRange, searchSessionId, isLinkedToOriginatingApp, ...emptyState } = getPreloadedState(storeDeps); const { attributeService, notifications, data, dashboardFeatureFlag } = lensServices; @@ -117,6 +123,8 @@ export function loadInitial( return initializeSources( { datasourceMap, + visualizationMap, + visualizationState: lens.visualization, datasourceStates: lens.datasourceStates, initialContext, adHocDataViews: lens.persistedDoc?.state.adHocDataViews, @@ -126,14 +134,14 @@ export function loadInitial( isFullEditor: true, } ) - .then(({ states, indexPatterns, indexPatternRefs }) => { + .then(({ datasourceStates, indexPatterns, indexPatternRefs }) => { store.dispatch( initEmpty({ newState: { ...emptyState, dataViews: getInitialDataViewsObject(indexPatterns, indexPatternRefs), searchSessionId: data.search.session.getSessionId() || data.search.session.start(), - datasourceStates: Object.entries(states).reduce( + datasourceStates: Object.entries(datasourceStates).reduce( (state, [datasourceId, datasourceState]) => ({ ...state, [datasourceId]: { @@ -187,9 +195,16 @@ export function loadInitial( const filters = data.query.filterManager.inject(doc.state.filters, doc.references); // Don't overwrite any pinned filters data.query.filterManager.setAppFilters(filters); + + const docVisualizationState = { + activeId: doc.visualizationType, + state: doc.state.visualization, + }; return initializeSources( { datasourceMap, + visualizationMap, + visualizationState: docVisualizationState, datasourceStates: docDatasourceStates, references: [...doc.references, ...(doc.state.internalReferences || [])], initialContext, @@ -200,7 +215,7 @@ export function loadInitial( }, { isFullEditor: true } ) - .then(({ states, indexPatterns, indexPatternRefs }) => { + .then(({ datasourceStates, visualizationState, indexPatterns, indexPatternRefs }) => { const currentSessionId = data.search.session.getSessionId(); store.dispatch( setState({ @@ -219,10 +234,10 @@ export function loadInitial( activeDatasourceId: getInitialDatasourceId(datasourceMap, doc), visualization: { activeId: doc.visualizationType, - state: doc.state.visualization, + state: visualizationState, }, dataViews: getInitialDataViewsObject(indexPatterns, indexPatternRefs), - datasourceStates: Object.entries(states).reduce( + datasourceStates: Object.entries(datasourceStates).reduce( (state, [datasourceId, datasourceState]) => ({ ...state, [datasourceId]: { diff --git a/x-pack/plugins/lens/public/state_management/lens_slice.test.ts b/x-pack/plugins/lens/public/state_management/lens_slice.test.ts index d38c0aed166767..fba5c9c9abd54d 100644 --- a/x-pack/plugins/lens/public/state_management/lens_slice.test.ts +++ b/x-pack/plugins/lens/public/state_management/lens_slice.test.ts @@ -227,6 +227,7 @@ describe('lensSlice', () => { removeLayer: (layerIds: unknown, layerId: string) => (layerIds as string[]).filter((id: string) => id !== layerId), insertLayer: (layerIds: unknown, layerId: string) => [...(layerIds as string[]), layerId], + getCurrentIndexPatternId: jest.fn(() => 'indexPattern1'), }; }; const datasourceStates = { diff --git a/x-pack/plugins/lens/public/state_management/lens_slice.ts b/x-pack/plugins/lens/public/state_management/lens_slice.ts index aaf34f62305c57..e7eaf6b9c38119 100644 --- a/x-pack/plugins/lens/public/state_management/lens_slice.ts +++ b/x-pack/plugins/lens/public/state_management/lens_slice.ts @@ -88,7 +88,10 @@ export const getPreloadedState = ({ }; export const setState = createAction>('lens/setState'); -export const onActiveDataChange = createAction('lens/onActiveDataChange'); +export const onActiveDataChange = createAction<{ + activeData: TableInspectorAdapter; + requestWarnings?: string[]; +}>('lens/onActiveDataChange'); export const setSaveable = createAction('lens/setSaveable'); export const enableAutoApply = createAction('lens/enableAutoApply'); export const disableAutoApply = createAction('lens/disableAutoApply'); @@ -222,10 +225,16 @@ export const makeLensReducer = (storeDeps: LensStoreDeps) => { ...payload, }; }, - [onActiveDataChange.type]: (state, { payload }: PayloadAction) => { + [onActiveDataChange.type]: ( + state, + { + payload: { activeData, requestWarnings }, + }: PayloadAction<{ activeData: TableInspectorAdapter; requestWarnings?: string[] }> + ) => { return { ...state, - activeData: payload, + activeData, + requestWarnings, }; }, [setSaveable.type]: (state, { payload }: PayloadAction) => { @@ -279,6 +288,7 @@ export const makeLensReducer = (storeDeps: LensStoreDeps) => { } ) => { const activeVisualization = visualizationMap[visualizationId]; + const activeDataSource = datasourceMap[state.activeDatasourceId!]; const isOnlyLayer = getRemoveOperation( activeVisualization, @@ -300,9 +310,13 @@ export const makeLensReducer = (storeDeps: LensStoreDeps) => { } ); state.stagedPreview = undefined; + // reuse the activeDatasource current dataView id for the moment + const currentDataViewsId = activeDataSource.getCurrentIndexPatternId( + state.datasourceStates[state.activeDatasourceId!].state + ); state.visualization.state = isOnlyLayer || !activeVisualization.removeLayer - ? activeVisualization.clearLayer(state.visualization.state, layerId) + ? activeVisualization.clearLayer(state.visualization.state, layerId, currentDataViewsId) : activeVisualization.removeLayer(state.visualization.state, layerId); }, [changeIndexPattern.type]: ( @@ -343,15 +357,15 @@ export const makeLensReducer = (storeDeps: LensStoreDeps) => { for (const visualizationId of visualizationIds) { const activeVisualization = visualizationId && - state.visualization.activeId !== visualizationId && + state.visualization.activeId === visualizationId && visualizationMap[visualizationId]; if (activeVisualization && layerId && activeVisualization?.onIndexPatternChange) { newState.visualization = { ...state.visualization, state: activeVisualization.onIndexPatternChange( state.visualization.state, - layerId, - indexPatternId + indexPatternId, + layerId ), }; } @@ -797,15 +811,20 @@ export const makeLensReducer = (storeDeps: LensStoreDeps) => { } const activeVisualization = visualizationMap[state.visualization.activeId]; + const activeDatasource = datasourceMap[state.activeDatasourceId]; + // reuse the active datasource dataView id for the new layer + const currentDataViewsId = activeDatasource.getCurrentIndexPatternId( + state.datasourceStates[state.activeDatasourceId!].state + ); const visualizationState = activeVisualization.appendLayer!( state.visualization.state, layerId, - layerType + layerType, + currentDataViewsId ); const framePublicAPI = selectFramePublicAPI({ lens: current(state) }, datasourceMap); - const activeDatasource = datasourceMap[state.activeDatasourceId]; const { noDatasource } = activeVisualization .getSupportedLayers(visualizationState, framePublicAPI) diff --git a/x-pack/plugins/lens/public/state_management/selectors.ts b/x-pack/plugins/lens/public/state_management/selectors.ts index 447eccd1705fde..54e3b420bbe363 100644 --- a/x-pack/plugins/lens/public/state_management/selectors.ts +++ b/x-pack/plugins/lens/public/state_management/selectors.ts @@ -28,10 +28,13 @@ export const selectVisualization = (state: LensState) => state.lens.visualizatio export const selectStagedPreview = (state: LensState) => state.lens.stagedPreview; export const selectStagedActiveData = (state: LensState) => state.lens.stagedPreview?.activeData || state.lens.activeData; +export const selectStagedRequestWarnings = (state: LensState) => + state.lens.stagedPreview?.requestWarnings || state.lens.requestWarnings; export const selectAutoApplyEnabled = (state: LensState) => !state.lens.autoApplyDisabled; export const selectChangesApplied = (state: LensState) => !state.lens.autoApplyDisabled || Boolean(state.lens.changesApplied); export const selectDatasourceStates = (state: LensState) => state.lens.datasourceStates; +export const selectVisualizationState = (state: LensState) => state.lens.visualization; export const selectActiveDatasourceId = (state: LensState) => state.lens.activeDatasourceId; export const selectActiveData = (state: LensState) => state.lens.activeData; export const selectDataViews = (state: LensState) => state.lens.dataViews; @@ -61,6 +64,7 @@ export const selectExecutionContextSearch = createSelector(selectExecutionContex to: res.dateRange.toDate, }, filters: res.filters, + disableShardWarnings: true, })); const selectInjectedDependencies = (_state: LensState, dependencies: unknown) => dependencies; @@ -94,7 +98,9 @@ export const selectSavedObjectFormat = createSelector( { datasourceMap, visualizationMap, extractFilterReferences } ) => { const activeVisualization = - visualization.state && visualization.activeId && visualizationMap[visualization.activeId]; + visualization.state && visualization.activeId + ? visualizationMap[visualization.activeId] + : null; const activeDatasource = datasourceStates && activeDatasourceId && !datasourceStates[activeDatasourceId].isLoading ? datasourceMap[activeDatasourceId] @@ -129,6 +135,20 @@ export const selectSavedObjectFormat = createSelector( }); }); + let persistibleVisualizationState = visualization.state; + if (activeVisualization.getPersistableState) { + const { state: persistableState, savedObjectReferences } = + activeVisualization.getPersistableState(visualization.state); + persistibleVisualizationState = persistableState; + savedObjectReferences.forEach((r) => { + if (r.type === 'index-pattern' && adHocDataViews[r.id]) { + internalReferences.push(r); + } else { + references.push(r); + } + }); + } + const persistableAdHocDataViews = Object.fromEntries( Object.entries(adHocDataViews).map(([id, dataView]) => { const { references: dataViewReferences, state } = @@ -159,7 +179,7 @@ export const selectSavedObjectFormat = createSelector( type: 'lens', references, state: { - visualization: visualization.state, + visualization: persistibleVisualizationState, query, filters: [...persistableFilters, ...adHocFilters], datasourceStates: persistibleDatasourceStates, diff --git a/x-pack/plugins/lens/public/state_management/types.ts b/x-pack/plugins/lens/public/state_management/types.ts index 7b461338261fc6..ceae38967c77d6 100644 --- a/x-pack/plugins/lens/public/state_management/types.ts +++ b/x-pack/plugins/lens/public/state_management/types.ts @@ -41,6 +41,7 @@ export interface PreviewState { visualization: VisualizationState; datasourceStates: DatasourceStates; activeData?: TableInspectorAdapter; + requestWarnings?: string[]; } export interface EditorFrameState extends PreviewState { activeDatasourceId: string | null; diff --git a/x-pack/plugins/lens/public/types.ts b/x-pack/plugins/lens/public/types.ts index 506b3fe459db2c..17950f8c5e50e6 100644 --- a/x-pack/plugins/lens/public/types.ts +++ b/x-pack/plugins/lens/public/types.ts @@ -18,6 +18,7 @@ import type { Datatable, } from '@kbn/expressions-plugin/public'; import type { VisualizeEditorLayersContext } from '@kbn/visualizations-plugin/public'; +import { Adapters } from '@kbn/inspector-plugin/public'; import type { Query } from '@kbn/es-query'; import type { UiActionsStart, @@ -28,6 +29,7 @@ import type { ClickTriggerEvent, BrushTriggerEvent } from '@kbn/charts-plugin/pu import type { IndexPatternAggRestrictions } from '@kbn/data-plugin/public'; import type { FieldSpec, DataViewSpec } from '@kbn/data-views-plugin/common'; import type { FieldFormatParams } from '@kbn/field-formats-plugin/common'; +import { SearchResponseWarning } from '@kbn/data-plugin/public/search/types'; import type { DraggingIdentifier, DragDropIdentifier, DragContextState } from './drag_drop'; import type { DateRange, LayerType, SortingHint } from '../common'; import type { @@ -46,7 +48,7 @@ import { import type { LensInspector } from './lens_inspector_service'; import type { FormatSelectorOptions } from './indexpattern_datasource/dimension_panel/format_selector'; import type { DataViewsState } from './state_management/types'; -import type { IndexPatternServiceAPI } from './indexpattern_service/service'; +import type { IndexPatternServiceAPI } from './data_views_service/service'; import type { Document } from './persistence/saved_object_store'; export interface IndexPatternRef { @@ -116,8 +118,8 @@ export interface EditorFrameSetup { registerDatasource: ( datasource: Datasource | (() => Promise>) ) => void; - registerVisualization: ( - visualization: Visualization | (() => Promise>) + registerVisualization: ( + visualization: Visualization | (() => Promise>) ) => void; } @@ -414,11 +416,16 @@ export interface Datasource { getWarningMessages?: ( state: T, frame: FramePublicAPI, + adapters: Adapters, setState: StateSetter ) => React.ReactNode[] | undefined; getDeprecationMessages?: (state: T) => React.ReactNode[] | undefined; + /** + * The embeddable calls this function to display warnings about visualization on the dashboard + */ + getSearchWarningMessages?: (state: P, warning: SearchResponseWarning) => string[] | undefined; /** * Checks if the visualization created is time based, for example date histogram */ @@ -449,6 +456,10 @@ export interface Datasource { * Get the used DataView value from state */ getUsedDataView: (state: T, layerId: string) => string; + /** + * Get all the used DataViews from state + */ + getUsedDataViews: (state: T) => string[]; } export interface DatasourceFixAction { @@ -510,6 +521,7 @@ export interface DatasourceDataPanelProps { uiActions: UiActionsStart; indexPatternService: IndexPatternServiceAPI; frame: FramePublicAPI; + usedIndexPatterns?: string[]; } interface SharedDimensionProps { @@ -631,6 +643,7 @@ export interface Operation extends OperationMetadata { } export interface OperationMetadata { + interval?: string; // The output of this operation will have this data type dataType: DataType; // A bucketed operation is grouped by duplicate values, otherwise each row is @@ -665,12 +678,10 @@ export interface VisualizationConfigProps { export type VisualizationLayerWidgetProps = VisualizationConfigProps & { setState: (newState: T) => void; - onChangeIndexPattern: (indexPatternId: string, layerId: string) => void; + onChangeIndexPattern: (indexPatternId: string) => void; }; -export type VisualizationLayerHeaderContentProps = VisualizationLayerWidgetProps & { - defaultIndexPatternId: string; -}; +export type VisualizationLayerHeaderContentProps = VisualizationLayerWidgetProps; export interface VisualizationToolbarProps { setState: (newState: T) => void; @@ -885,18 +896,23 @@ export interface VisualizationDisplayOptions { noPadding?: boolean; } -export interface Visualization { +export interface Visualization { /** Plugin ID, such as "lnsXY" */ id: string; /** * Initialize is allowed to modify the state stored in memory. The initialize function * is called with a previous state in two cases: - * - Loadingn from a saved visualization + * - Loading from a saved visualization * - When using suggestions, the suggested state is passed in */ initialize: (addNewLayer: () => string, state?: T, mainPalette?: PaletteOutput) => T; + /** + * Retrieve the used DataViews in the visualization + */ + getUsedDataViews?: (state?: T) => string[]; + getMainPalette?: (state: T) => undefined | PaletteOutput; /** @@ -919,15 +935,18 @@ export interface Visualization { switchVisualizationType?: (visualizationTypeId: string, state: T) => T; /** Description is displayed as the clickable text in the chart switcher */ getDescription: (state: T) => { icon?: IconType; label: string }; - + /** Visualizations can have references as well */ + getPersistableState?: (state: T) => { state: P; savedObjectReferences: SavedObjectReference[] }; + /** Hydrate from persistable state and references to final state */ + fromPersistableState?: (state: P, references?: SavedObjectReference[]) => T; /** Frame needs to know which layers the visualization is currently using */ getLayerIds: (state: T) => string[]; /** Reset button on each layer triggers this */ - clearLayer: (state: T, layerId: string) => T; + clearLayer: (state: T, layerId: string, indexPatternId: string) => T; /** Optional, if the visualization supports multiple layers */ removeLayer?: (state: T, layerId: string) => T; /** Track added layers in internal state */ - appendLayer?: (state: T, layerId: string, type: LayerType, indexPatternId?: string) => T; + appendLayer?: (state: T, layerId: string, type: LayerType, indexPatternId: string) => T; /** Retrieve a list of supported layer types with initialization data */ getSupportedLayers: ( @@ -1081,7 +1100,7 @@ export interface Visualization { */ getErrorMessages: ( state: T, - datasourceLayers?: DatasourceLayers + frame?: Pick ) => | Array<{ shortMessage: string; @@ -1089,6 +1108,14 @@ export interface Visualization { }> | undefined; + validateColumn?: ( + state: T, + frame: Pick, + layerId: string, + columnId: string, + group?: VisualizationDimensionGroupConfig + ) => { invalid: boolean; invalidMessage?: string }; + /** * The frame calls this function to display warnings about visualization */ diff --git a/x-pack/plugins/lens/public/utils.ts b/x-pack/plugins/lens/public/utils.ts index 717d0e9f996b99..385a533dc7c754 100644 --- a/x-pack/plugins/lens/public/utils.ts +++ b/x-pack/plugins/lens/public/utils.ts @@ -22,7 +22,7 @@ import type { IndexPatternRef, } from './types'; import type { DatasourceStates, VisualizationState } from './state_management'; -import { IndexPatternServiceAPI } from './indexpattern_service/service'; +import { IndexPatternServiceAPI } from './data_views_service/service'; export function getVisualizeGeoFieldMessage(fieldType: string) { return i18n.translate('xpack.lens.visualizeGeoFieldMessage', { @@ -113,9 +113,13 @@ export async function refreshIndexPatternsList({ export function getIndexPatternsIds({ activeDatasources, datasourceStates, + visualizationState, + activeVisualization, }: { activeDatasources: Record; datasourceStates: DatasourceStates; + visualizationState: unknown; + activeVisualization?: Visualization; }): string[] { let currentIndexPatternId: string | undefined; const references: SavedObjectReference[] = []; @@ -125,6 +129,11 @@ export function getIndexPatternsIds({ currentIndexPatternId = indexPatternId; references.push(...savedObjectReferences); }); + + if (activeVisualization?.getPersistableState) { + const { savedObjectReferences } = activeVisualization.getPersistableState(visualizationState); + references.push(...savedObjectReferences); + } const referencesIds = references .filter(({ type }) => type === 'index-pattern') .map(({ id }) => id); diff --git a/x-pack/plugins/lens/public/visualizations/datatable/visualization.test.tsx b/x-pack/plugins/lens/public/visualizations/datatable/visualization.test.tsx index 494be445670ae1..85d1bc3f1a5753 100644 --- a/x-pack/plugins/lens/public/visualizations/datatable/visualization.test.tsx +++ b/x-pack/plugins/lens/public/visualizations/datatable/visualization.test.tsx @@ -70,7 +70,7 @@ describe('Datatable Visualization', () => { layerType: layerTypes.DATA, columns: [{ columnId: 'a' }, { columnId: 'b' }, { columnId: 'c' }], }; - expect(datatableVisualization.clearLayer(state, 'baz')).toMatchObject({ + expect(datatableVisualization.clearLayer(state, 'baz', 'indexPattern1')).toMatchObject({ layerId: 'baz', layerType: layerTypes.DATA, columns: [], diff --git a/x-pack/plugins/lens/public/visualizations/datatable/visualization.tsx b/x-pack/plugins/lens/public/visualizations/datatable/visualization.tsx index d106643a205e39..8cc30c65ed1a99 100644 --- a/x-pack/plugins/lens/public/visualizations/datatable/visualization.tsx +++ b/x-pack/plugins/lens/public/visualizations/datatable/visualization.tsx @@ -223,10 +223,10 @@ export const getDatatableVisualization = ({ { groupId: 'columns', groupLabel: i18n.translate('xpack.lens.datatable.breakdownColumns', { - defaultMessage: 'Columns', + defaultMessage: 'Split metrics by', }), dimensionEditorGroupLabel: i18n.translate('xpack.lens.datatable.breakdownColumn', { - defaultMessage: 'Column', + defaultMessage: 'Split metrics by', }), groupTooltip: i18n.translate('xpack.lens.datatable.breakdownColumns.description', { defaultMessage: diff --git a/x-pack/plugins/lens/public/visualizations/legacy_metric/visualization.test.ts b/x-pack/plugins/lens/public/visualizations/legacy_metric/visualization.test.ts index fb8493fc4d0f52..c8a1b18e392c5f 100644 --- a/x-pack/plugins/lens/public/visualizations/legacy_metric/visualization.test.ts +++ b/x-pack/plugins/lens/public/visualizations/legacy_metric/visualization.test.ts @@ -70,7 +70,7 @@ describe('metric_visualization', () => { describe('#clearLayer', () => { it('returns a clean layer', () => { (generateId as jest.Mock).mockReturnValueOnce('test-id1'); - expect(metricVisualization.clearLayer(exampleState(), 'l1')).toEqual({ + expect(metricVisualization.clearLayer(exampleState(), 'l1', 'indexPattern1')).toEqual({ accessor: undefined, layerId: 'l1', layerType: layerTypes.DATA, diff --git a/x-pack/plugins/lens/public/visualizations/metric/visualization.test.ts b/x-pack/plugins/lens/public/visualizations/metric/visualization.test.ts index 18e664ce4ea36f..8171bd379237e2 100644 --- a/x-pack/plugins/lens/public/visualizations/metric/visualization.test.ts +++ b/x-pack/plugins/lens/public/visualizations/metric/visualization.test.ts @@ -515,7 +515,7 @@ describe('metric visualization', () => { }); it('clears a layer', () => { - expect(visualization.clearLayer(fullState, 'some-id')).toMatchInlineSnapshot(` + expect(visualization.clearLayer(fullState, 'some-id', 'indexPattern1')).toMatchInlineSnapshot(` Object { "layerId": "first", "layerType": "data", diff --git a/x-pack/plugins/lens/public/visualizations/xy/__snapshots__/to_expression.test.ts.snap b/x-pack/plugins/lens/public/visualizations/xy/__snapshots__/to_expression.test.ts.snap index c69a3f0567a3ca..e040232581962e 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/__snapshots__/to_expression.test.ts.snap +++ b/x-pack/plugins/lens/public/visualizations/xy/__snapshots__/to_expression.test.ts.snap @@ -8,6 +8,7 @@ Object { "addTimeMarker": Array [ false, ], + "annotations": Array [], "emphasizeFitting": Array [ true, ], diff --git a/x-pack/plugins/lens/public/visualizations/xy/annotations/helpers.test.ts b/x-pack/plugins/lens/public/visualizations/xy/annotations/helpers.test.ts index 8560e3bbaec311..d953814621aad6 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/annotations/helpers.test.ts +++ b/x-pack/plugins/lens/public/visualizations/xy/annotations/helpers.test.ts @@ -5,24 +5,21 @@ * 2.0. */ +import { createMockFramePublicAPI } from '../../../mocks'; import { FramePublicAPI } from '../../../types'; import { getStaticDate } from './helpers'; -const frame: FramePublicAPI = { - datasourceLayers: {}, - dateRange: { fromDate: '2022-02-01T00:00:00.000Z', toDate: '2022-04-20T00:00:00.000Z' }, - dataViews: { - indexPatterns: {}, - indexPatternRefs: [], - existingFields: {}, - isFirstExistenceFetch: true, - }, -}; - describe('annotations helpers', () => { describe('getStaticDate', () => { it('should return the middle of the date range on when nothing is configured', () => { - expect(getStaticDate([], frame)).toBe('2022-03-12T00:00:00.000Z'); + expect( + getStaticDate( + [], + createMockFramePublicAPI({ + dateRange: { fromDate: '2022-02-01T00:00:00.000Z', toDate: '2022-04-20T00:00:00.000Z' }, + }) + ) + ).toBe('2022-03-12T00:00:00.000Z'); }); it('should return the middle of the date range value on when there is no active data', () => { expect( @@ -36,7 +33,9 @@ describe('annotations helpers', () => { xAccessor: 'a', }, ], - frame + createMockFramePublicAPI({ + dateRange: { fromDate: '2022-02-01T00:00:00.000Z', toDate: '2022-04-20T00:00:00.000Z' }, + }) ) ).toBe('2022-03-12T00:00:00.000Z'); }); @@ -64,7 +63,7 @@ describe('annotations helpers', () => { }, ], }, - }; + } as FramePublicAPI['activeData']; expect( getStaticDate( [ @@ -76,10 +75,10 @@ describe('annotations helpers', () => { xAccessor: 'a', }, ], - { - ...frame, - activeData: activeData as FramePublicAPI['activeData'], - } + createMockFramePublicAPI({ + dateRange: { fromDate: '2022-02-01T00:00:00.000Z', toDate: '2022-04-20T00:00:00.000Z' }, + activeData, + }) ) ).toBe('2022-02-27T23:00:00.000Z'); }); @@ -107,7 +106,7 @@ describe('annotations helpers', () => { }, ], }, - }; + } as FramePublicAPI['activeData']; expect( getStaticDate( [ @@ -119,10 +118,10 @@ describe('annotations helpers', () => { xAccessor: 'a', }, ], - { - ...frame, - activeData: activeData as FramePublicAPI['activeData'], - } + createMockFramePublicAPI({ + dateRange: { fromDate: '2022-02-01T00:00:00.000Z', toDate: '2022-04-20T00:00:00.000Z' }, + activeData, + }) ) ).toBe('2022-03-12T00:00:00.000Z'); }); @@ -162,7 +161,7 @@ describe('annotations helpers', () => { }, ], }, - }; + } as FramePublicAPI['activeData']; expect( getStaticDate( [ @@ -174,10 +173,10 @@ describe('annotations helpers', () => { xAccessor: 'a', }, ], - { - ...frame, - activeData: activeData as FramePublicAPI['activeData'], - } + createMockFramePublicAPI({ + dateRange: { fromDate: '2022-02-01T00:00:00.000Z', toDate: '2022-04-20T00:00:00.000Z' }, + activeData, + }) ) ).toBe('2022-03-26T05:00:00.000Z'); }); @@ -242,7 +241,7 @@ describe('annotations helpers', () => { }, ], }, - }; + } as FramePublicAPI['activeData']; expect( getStaticDate( [ @@ -261,11 +260,11 @@ describe('annotations helpers', () => { xAccessor: 'd', }, ], - { - ...frame, + + createMockFramePublicAPI({ + activeData, dateRange: { fromDate: '2020-02-01T00:00:00.000Z', toDate: '2022-09-20T00:00:00.000Z' }, - activeData: activeData as FramePublicAPI['activeData'], - } + }) ) ).toBe('2020-08-24T12:06:40.000Z'); }); diff --git a/x-pack/plugins/lens/public/visualizations/xy/annotations/helpers.tsx b/x-pack/plugins/lens/public/visualizations/xy/annotations/helpers.tsx index a84e7a3c3ed194..b45e79cc018e8d 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/annotations/helpers.tsx +++ b/x-pack/plugins/lens/public/visualizations/xy/annotations/helpers.tsx @@ -120,6 +120,7 @@ export const getAnnotationsSupportedLayer = ( const getDefaultAnnotationConfig = (id: string, timestamp: string): EventAnnotationConfig => ({ label: defaultAnnotationLabel, + type: 'manual', key: { type: 'point_in_time', timestamp, diff --git a/x-pack/plugins/lens/public/visualizations/xy/index.ts b/x-pack/plugins/lens/public/visualizations/xy/index.ts index 37d4f46a5bcc72..9dcd1dab635938 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/index.ts +++ b/x-pack/plugins/lens/public/visualizations/xy/index.ts @@ -32,8 +32,10 @@ export class XyVisualization { const { getXyVisualization } = await import('../../async_services'); const [coreStart, { charts, data, fieldFormats, eventAnnotation }] = await core.getStartServices(); - const palettes = await charts.palettes.getPalettes(); - const eventAnnotationService = await eventAnnotation.getService(); + const [palettes, eventAnnotationService] = await Promise.all([ + charts.palettes.getPalettes(), + eventAnnotation.getService(), + ]); const useLegacyTimeAxis = core.uiSettings.get(LEGACY_TIME_AXIS); return getXyVisualization({ core: coreStart, diff --git a/x-pack/plugins/lens/public/visualizations/xy/state_helpers.ts b/x-pack/plugins/lens/public/visualizations/xy/state_helpers.ts index d1fcfdc1c7997b..37c08fc7e8668f 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/state_helpers.ts +++ b/x-pack/plugins/lens/public/visualizations/xy/state_helpers.ts @@ -5,8 +5,17 @@ * 2.0. */ +import { DistributiveOmit } from '@elastic/eui'; import { EuiIconType } from '@elastic/eui/src/components/icon/icon'; -import type { FramePublicAPI, DatasourcePublicAPI } from '../../types'; +import type { SavedObjectReference } from '@kbn/core/public'; +import { isQueryAnnotationConfig } from '@kbn/event-annotation-plugin/public'; +import { i18n } from '@kbn/i18n'; +import { validateQuery } from '../../shared_components'; +import type { + FramePublicAPI, + DatasourcePublicAPI, + VisualizationDimensionGroupConfig, +} from '../../types'; import { visualizationTypes, XYLayerConfig, @@ -14,6 +23,9 @@ import { XYReferenceLineLayerConfig, SeriesType, YConfig, + XYState, + XYPersistedState, + State, } from './types'; import { getDataLayers, isAnnotationsLayer, isDataLayer } from './visualization_helpers'; @@ -102,3 +114,129 @@ export function hasHistogramSeries( ); }); } + +function getLayerReferenceName(layerId: string) { + return `xy-visualization-layer-${layerId}`; +} + +export function extractReferences(state: XYState) { + const savedObjectReferences: SavedObjectReference[] = []; + const persistableLayers: Array> = []; + state.layers.forEach((layer) => { + if (isAnnotationsLayer(layer)) { + const { indexPatternId, ...persistableLayer } = layer; + savedObjectReferences.push({ + type: 'index-pattern', + id: indexPatternId, + name: getLayerReferenceName(layer.layerId), + }); + persistableLayers.push(persistableLayer); + } else { + persistableLayers.push(layer); + } + }); + return { savedObjectReferences, state: { ...state, layers: persistableLayers } }; +} + +export function injectReferences( + state: XYPersistedState, + references?: SavedObjectReference[] +): XYState { + if (!references || !references.length) { + return state as XYState; + } + const fallbackIndexPatternId = references.find(({ type }) => type === 'index-pattern')!.id; + return { + ...state, + layers: state.layers.map((layer) => { + if (!isAnnotationsLayer(layer)) { + return layer as XYLayerConfig; + } + return { + ...layer, + indexPatternId: + references.find(({ name }) => name === getLayerReferenceName(layer.layerId))?.id || + fallbackIndexPatternId, + }; + }), + }; +} + +export function validateColumn( + state: State, + frame: Pick, + layerId: string, + columnId: string, + group?: VisualizationDimensionGroupConfig +): { invalid: boolean; invalidMessages?: string[] } { + if (group?.invalid) { + return { + invalid: true, + invalidMessages: group.invalidMessage ? [group.invalidMessage] : undefined, + }; + } + const validColumn = { invalid: false }; + const layer = state.layers.find((l) => l.layerId === layerId); + if (!layer || !isAnnotationsLayer(layer)) { + return validColumn; + } + const annotation = layer.annotations.find(({ id }) => id === columnId); + if (!annotation || !isQueryAnnotationConfig(annotation)) { + return validColumn; + } + const { dataViews } = frame || {}; + const layerDataView = dataViews.indexPatterns[layer.indexPatternId]; + + const invalidMessages: string[] = []; + + if (annotation.timeField && !Boolean(layerDataView.getFieldByName(annotation.timeField))) { + invalidMessages.push( + i18n.translate('xpack.lens.xyChart.annotationError.timeFieldNotFound', { + defaultMessage: 'Time field {timeField} not found in data view {dataView}', + values: { timeField: annotation.timeField, dataView: layerDataView.title }, + }) + ); + } + + const { isValid, error } = validateQuery(annotation?.filter, layerDataView); + if (!isValid && error) { + invalidMessages.push(error); + } + if (annotation.textField && !Boolean(layerDataView.getFieldByName(annotation.textField))) { + invalidMessages.push( + i18n.translate('xpack.lens.xyChart.annotationError.textFieldNotFound', { + defaultMessage: 'Text field {textField} not found in data view {dataView}', + values: { textField: annotation.textField, dataView: layerDataView.title }, + }) + ); + } + if (annotation.extraFields?.length) { + const missingTooltipFields = []; + for (const field of annotation.extraFields) { + if (!Boolean(layerDataView.getFieldByName(field))) { + missingTooltipFields.push(field); + } + } + if (missingTooltipFields.length) { + invalidMessages.push( + i18n.translate('xpack.lens.xyChart.annotationError.tooltipFieldNotFound', { + defaultMessage: + 'Tooltip {missingFields, plural, one {field} other {fields}} {missingTooltipFields} not found in data view {dataView}', + values: { + missingTooltipFields: missingTooltipFields.join(', '), + missingFields: missingTooltipFields.length, + dataView: layerDataView.title, + }, + }) + ); + } + } + + if (!invalidMessages.length) { + return validColumn; + } + return { + invalid: true, + invalidMessages, + }; +} diff --git a/x-pack/plugins/lens/public/visualizations/xy/to_expression.test.ts b/x-pack/plugins/lens/public/visualizations/xy/to_expression.test.ts index e5faf9c2682adc..124e7e8e1ddd32 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/to_expression.test.ts +++ b/x-pack/plugins/lens/public/visualizations/xy/to_expression.test.ts @@ -539,6 +539,38 @@ describe('#toExpression', () => { expect(getYConfigColorForLayer(expression, 1)).toEqual([defaultReferenceLineColor]); }); + it('should ignore annotation layers with no event configured', () => { + const expression = xyVisualization.toExpression( + { + legend: { position: Position.Bottom, isVisible: true }, + valueLabels: 'show', + preferredSeriesType: 'bar', + layers: [ + { + layerId: 'first', + layerType: layerTypes.DATA, + seriesType: 'area', + splitAccessor: 'd', + xAccessor: 'a', + accessors: ['b', 'c'], + yConfig: [{ forAccessor: 'a' }], + }, + { + layerId: 'first', + layerType: layerTypes.ANNOTATIONS, + annotations: [], + indexPatternId: 'my-indexPattern', + }, + ], + }, + { ...frame.datasourceLayers, referenceLine: mockDatasource.publicAPIMock }, + undefined, + datasourceExpressionsByLayers + ) as Ast; + + expect(expression.chain[0].arguments.layers).toHaveLength(1); + }); + it('should correctly set the current time marker visibility settings', () => { const state: XYState = { legend: { position: Position.Bottom, isVisible: true }, diff --git a/x-pack/plugins/lens/public/visualizations/xy/to_expression.ts b/x-pack/plugins/lens/public/visualizations/xy/to_expression.ts index 387542e5465f82..bfe722a21f9792 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/to_expression.ts +++ b/x-pack/plugins/lens/public/visualizations/xy/to_expression.ts @@ -8,9 +8,14 @@ import { Ast, AstFunction } from '@kbn/interpreter'; import { Position, ScaleType } from '@elastic/charts'; import type { PaletteRegistry } from '@kbn/coloring'; -import { EventAnnotationServiceType } from '@kbn/event-annotation-plugin/public'; +import { + EventAnnotationServiceType, + isManualPointAnnotationConfig, + isRangeAnnotationConfig, +} from '@kbn/event-annotation-plugin/public'; import { LegendSize } from '@kbn/visualizations-plugin/public'; import { XYCurveType } from '@kbn/expression-xy-plugin/common'; +import { EventAnnotationConfig } from '@kbn/event-annotation-plugin/common'; import { State, YConfig, @@ -241,6 +246,11 @@ export const buildExpression = ( }); } + const isValidAnnotation = (a: EventAnnotationConfig) => + isManualPointAnnotationConfig(a) || + isRangeAnnotationConfig(a) || + (a.filter && a.filter?.query !== ''); + return { type: 'expression', chain: [ @@ -343,10 +353,39 @@ export const buildExpression = ( datasourceExpressionsByLayers[layer.layerId] ) ), - ...validAnnotationsLayers.map((layer) => - annotationLayerToExpression(layer, eventAnnotationService) - ), ], + annotations: + validAnnotationsLayers.length && + validAnnotationsLayers.flatMap((l) => l.annotations.filter(isValidAnnotation)).length + ? [ + { + type: 'expression', + chain: [ + { + type: 'function', + function: 'event_annotations_result', + arguments: { + layers: validAnnotationsLayers.map((layer) => + annotationLayerToExpression(layer, eventAnnotationService) + ), + datatable: eventAnnotationService.toFetchExpression({ + interval: + (validDataLayers[0]?.xAccessor && + metadata[validDataLayers[0]?.layerId]?.[ + validDataLayers[0]?.xAccessor + ]?.interval) || + 'auto', + groups: validAnnotationsLayers.map((layer) => ({ + indexPatternId: layer.indexPatternId, + annotations: layer.annotations.filter(isValidAnnotation), + })), + }), + }, + }, + ], + }, + ] + : [], }, }, ], @@ -416,9 +455,7 @@ const annotationLayerToExpression = ( arguments: { simpleView: [Boolean(layer.simpleView)], layerId: [layer.layerId], - annotations: layer.annotations - ? layer.annotations.map((ann): Ast => eventAnnotationService.toExpression(ann)) - : [], + annotations: eventAnnotationService.toExpression(layer.annotations || []), }, }, ], diff --git a/x-pack/plugins/lens/public/visualizations/xy/types.ts b/x-pack/plugins/lens/public/visualizations/xy/types.ts index 27c5d485065c87..203718e4b9f8cf 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/types.ts +++ b/x-pack/plugins/lens/public/visualizations/xy/types.ts @@ -35,6 +35,7 @@ import { IconChartBarHorizontal, } from '@kbn/chart-icons'; +import { DistributiveOmit } from '@elastic/eui'; import type { VisualizationType, Suggestion } from '../../types'; import type { ValueLabelConfig } from '../../../common/types'; @@ -115,6 +116,8 @@ export interface XYAnnotationLayerConfig { layerId: string; layerType: 'annotations'; annotations: EventAnnotationConfig[]; + hide?: boolean; + indexPatternId: string; simpleView?: boolean; } @@ -160,6 +163,12 @@ export interface XYState { export type State = XYState; +export type XYPersistedState = Omit & { + layers: Array>; +}; + +export type PersistedState = XYPersistedState; + const groupLabelForBar = i18n.translate('xpack.lens.xyVisualization.barGroupLabel', { defaultMessage: 'Bar', }); diff --git a/x-pack/plugins/lens/public/visualizations/xy/visualization.test.ts b/x-pack/plugins/lens/public/visualizations/xy/visualization.test.ts index ad26ea92762bf7..596f20d9fe2e7c 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/visualization.test.ts +++ b/x-pack/plugins/lens/public/visualizations/xy/visualization.test.ts @@ -35,9 +35,13 @@ import { eventAnnotationServiceMock } from '@kbn/event-annotation-plugin/public/ import { EventAnnotationConfig } from '@kbn/event-annotation-plugin/common'; import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; import { IStorageWrapper } from '@kbn/kibana-utils-plugin/public'; +import { DataViewsState } from '../../state_management'; +import { createMockedIndexPattern } from '../../indexpattern_datasource/mocks'; +import { createMockDataViewsState } from '../../data_views_service/mocks'; const exampleAnnotation: EventAnnotationConfig = { id: 'an1', + type: 'manual', label: 'Event 1', key: { type: 'point_in_time', @@ -47,6 +51,7 @@ const exampleAnnotation: EventAnnotationConfig = { }; const exampleAnnotation2: EventAnnotationConfig = { icon: 'circle', + type: 'manual', id: 'an2', key: { timestamp: '2022-04-18T11:01:59.135Z', @@ -237,7 +242,12 @@ describe('xy_visualization', () => { describe('#appendLayer', () => { it('adds a layer', () => { - const layers = xyVisualization.appendLayer!(exampleState(), 'foo', layerTypes.DATA).layers; + const layers = xyVisualization.appendLayer!( + exampleState(), + 'foo', + layerTypes.DATA, + 'indexPattern1' + ).layers; expect(layers.length).toEqual(exampleState().layers.length + 1); expect(layers[layers.length - 1]).toMatchObject({ layerId: 'foo' }); }); @@ -245,7 +255,7 @@ describe('xy_visualization', () => { describe('#clearLayer', () => { it('clears the specified layer', () => { - const layer = xyVisualization.clearLayer(exampleState(), 'first').layers[0]; + const layer = xyVisualization.clearLayer(exampleState(), 'first', 'indexPattern1').layers[0]; expect(layer).toMatchObject({ accessors: [], layerId: 'first', @@ -460,6 +470,7 @@ describe('xy_visualization', () => { { layerId: 'annotation', layerType: layerTypes.ANNOTATIONS, + indexPatternId: 'indexPattern1', annotations: [exampleAnnotation], }, ], @@ -471,10 +482,12 @@ describe('xy_visualization', () => { ).toEqual({ layerId: 'annotation', layerType: layerTypes.ANNOTATIONS, + indexPatternId: 'indexPattern1', annotations: [ exampleAnnotation, { icon: 'triangle', + type: 'manual', id: 'newCol', key: { timestamp: '2022-04-15T00:00:00.000Z', @@ -495,6 +508,7 @@ describe('xy_visualization', () => { { layerId: 'annotation', layerType: layerTypes.ANNOTATIONS, + indexPatternId: 'indexPattern1', annotations: [exampleAnnotation2], }, ], @@ -517,6 +531,7 @@ describe('xy_visualization', () => { ).toEqual({ layerId: 'annotation', layerType: layerTypes.ANNOTATIONS, + indexPatternId: 'indexPattern1', annotations: [exampleAnnotation2, { ...exampleAnnotation2, id: 'newColId' }], }); }); @@ -530,6 +545,7 @@ describe('xy_visualization', () => { { layerId: 'annotation', layerType: layerTypes.ANNOTATIONS, + indexPatternId: 'indexPattern1', annotations: [exampleAnnotation, exampleAnnotation2], }, ], @@ -553,6 +569,7 @@ describe('xy_visualization', () => { ).toEqual({ layerId: 'annotation', layerType: layerTypes.ANNOTATIONS, + indexPatternId: 'indexPattern1', annotations: [exampleAnnotation2, exampleAnnotation], }); }); @@ -566,12 +583,14 @@ describe('xy_visualization', () => { layers: [ { layerId: 'first', - layerType: 'annotations', + layerType: layerTypes.ANNOTATIONS, + indexPatternId: 'indexPattern1', annotations: [exampleAnnotation], }, { layerId: 'second', - layerType: 'annotations', + layerType: layerTypes.ANNOTATIONS, + indexPatternId: 'indexPattern1', annotations: [exampleAnnotation2], }, ], @@ -596,11 +615,13 @@ describe('xy_visualization', () => { { layerId: 'first', layerType: layerTypes.ANNOTATIONS, + indexPatternId: 'indexPattern1', annotations: [exampleAnnotation], }, { layerId: 'second', layerType: layerTypes.ANNOTATIONS, + indexPatternId: 'indexPattern1', annotations: [{ ...exampleAnnotation, id: 'an2' }], }, ]); @@ -614,12 +635,14 @@ describe('xy_visualization', () => { layers: [ { layerId: 'first', - layerType: 'annotations', + layerType: layerTypes.ANNOTATIONS, + indexPatternId: 'indexPattern1', annotations: [exampleAnnotation], }, { layerId: 'second', - layerType: 'annotations', + layerType: layerTypes.ANNOTATIONS, + indexPatternId: 'indexPattern1', annotations: [exampleAnnotation2], }, ], @@ -644,11 +667,13 @@ describe('xy_visualization', () => { { layerId: 'first', layerType: layerTypes.ANNOTATIONS, + indexPatternId: 'indexPattern1', annotations: [exampleAnnotation2], }, { layerId: 'second', layerType: layerTypes.ANNOTATIONS, + indexPatternId: 'indexPattern1', annotations: [exampleAnnotation], }, ]); @@ -662,12 +687,14 @@ describe('xy_visualization', () => { layers: [ { layerId: 'first', - layerType: 'annotations', + layerType: layerTypes.ANNOTATIONS, + indexPatternId: 'indexPattern1', annotations: [exampleAnnotation], }, { layerId: 'second', - layerType: 'annotations', + layerType: layerTypes.ANNOTATIONS, + indexPatternId: 'indexPattern1', annotations: [exampleAnnotation2], }, ], @@ -692,11 +719,13 @@ describe('xy_visualization', () => { { layerId: 'first', layerType: layerTypes.ANNOTATIONS, + indexPatternId: 'indexPattern1', annotations: [], }, { layerId: 'second', layerType: layerTypes.ANNOTATIONS, + indexPatternId: 'indexPattern1', annotations: [exampleAnnotation], }, ]); @@ -710,12 +739,14 @@ describe('xy_visualization', () => { layers: [ { layerId: 'first', - layerType: 'annotations', + layerType: layerTypes.ANNOTATIONS, + indexPatternId: 'indexPattern1', annotations: [exampleAnnotation], }, { layerId: 'second', - layerType: 'annotations', + layerType: layerTypes.ANNOTATIONS, + indexPatternId: 'indexPattern1', annotations: [], }, ], @@ -740,11 +771,13 @@ describe('xy_visualization', () => { { layerId: 'first', layerType: layerTypes.ANNOTATIONS, + indexPatternId: 'indexPattern1', annotations: [], }, { layerId: 'second', layerType: layerTypes.ANNOTATIONS, + indexPatternId: 'indexPattern1', annotations: [exampleAnnotation], }, ]); @@ -1106,6 +1139,7 @@ describe('xy_visualization', () => { { layerId: 'ann', layerType: layerTypes.ANNOTATIONS, + indexPatternId: 'indexPattern1', annotations: [exampleAnnotation, { ...exampleAnnotation, id: 'an2' }], }, ], @@ -1124,6 +1158,7 @@ describe('xy_visualization', () => { { layerId: 'ann', layerType: layerTypes.ANNOTATIONS, + indexPatternId: 'indexPattern1', annotations: [exampleAnnotation], }, ]); @@ -1843,6 +1878,7 @@ describe('xy_visualization', () => { { layerId: 'annotations', layerType: layerTypes.ANNOTATIONS, + indexPatternId: 'indexPattern1', annotations: [exampleAnnotation], }, ], @@ -2278,7 +2314,7 @@ describe('xy_visualization', () => { }, ], }, - frame.datasourceLayers + { datasourceLayers: frame.datasourceLayers, dataViews: {} as DataViewsState } ) ).toEqual([ { @@ -2334,7 +2370,7 @@ describe('xy_visualization', () => { }, ], }, - datasourceLayers + { datasourceLayers, dataViews: {} as DataViewsState } ) ).toEqual([ { @@ -2390,7 +2426,7 @@ describe('xy_visualization', () => { }, ], }, - datasourceLayers + { datasourceLayers, dataViews: {} as DataViewsState } ) ).toEqual([ { @@ -2399,6 +2435,98 @@ describe('xy_visualization', () => { }, ]); }); + + describe('Annotation layers', () => { + function createStateWithAnnotationProps(annotation: Partial) { + return { + layers: [ + { + layerId: 'layerId', + layerType: 'annotations', + indexPatternId: 'first', + annotations: [ + { + label: 'Event', + id: '1', + type: 'query', + timeField: 'start_date', + ...annotation, + }, + ], + }, + ], + } as XYState; + } + + function getFrameMock() { + return createMockFramePublicAPI({ + datasourceLayers: { first: mockDatasource.publicAPIMock }, + dataViews: createMockDataViewsState({ + indexPatterns: { first: createMockedIndexPattern() }, + }), + }); + } + it('should return error if current annotation contains non-existent field as timeField', () => { + const xyState = createStateWithAnnotationProps({ + timeField: 'non-existent', + }); + const errors = xyVisualization.getErrorMessages(xyState, getFrameMock()); + expect(errors).toHaveLength(1); + expect(errors![0]).toEqual( + expect.objectContaining({ + shortMessage: 'Time field non-existent not found in data view my-fake-index-pattern', + }) + ); + }); + it('should return error if current annotation contains non existent field as textField', () => { + const xyState = createStateWithAnnotationProps({ + textField: 'non-existent', + }); + const errors = xyVisualization.getErrorMessages(xyState, getFrameMock()); + expect(errors).toHaveLength(1); + expect(errors![0]).toEqual( + expect.objectContaining({ + shortMessage: 'Text field non-existent not found in data view my-fake-index-pattern', + }) + ); + }); + it('should contain error if current annotation contains at least one non-existent field as tooltip field', () => { + const xyState = createStateWithAnnotationProps({ + extraFields: ['bytes', 'memory', 'non-existent'], + }); + const errors = xyVisualization.getErrorMessages(xyState, getFrameMock()); + expect(errors).toHaveLength(1); + expect(errors![0]).toEqual( + expect.objectContaining({ + shortMessage: 'Tooltip field non-existent not found in data view my-fake-index-pattern', + }) + ); + }); + it('should contain error if current annotation contains invalid query', () => { + const xyState = createStateWithAnnotationProps({ + filter: { type: 'kibana_query', query: 'invalid: "', language: 'kuery' }, + }); + const errors = xyVisualization.getErrorMessages(xyState, getFrameMock()); + expect(errors).toHaveLength(1); + expect(errors![0]).toEqual( + expect.objectContaining({ + shortMessage: expect.stringContaining( + 'Expected "(", "{", value, whitespace but """ found.' + ), + }) + ); + }); + it('should contain multiple errors if current annotation contains multiple non-existent fields', () => { + const xyState = createStateWithAnnotationProps({ + timeField: 'non-existent', + textField: 'non-existent', + extraFields: ['bytes', 'memory', 'non-existent'], + filter: { type: 'kibana_query', query: 'invalid: "', language: 'kuery' }, + }); + const errors = xyVisualization.getErrorMessages(xyState, getFrameMock()); + expect(errors).toHaveLength(4); + }); + }); }); describe('#getWarningMessages', () => { @@ -2555,4 +2683,80 @@ describe('xy_visualization', () => { }); }); }); + + describe('#fromPersistableState', () => { + it('should inject references on annotation layers', () => { + const baseState = exampleState(); + expect( + xyVisualization.fromPersistableState!( + { + ...baseState, + layers: [ + ...baseState.layers, + { + layerId: 'annotation', + layerType: layerTypes.ANNOTATIONS, + annotations: [exampleAnnotation2], + }, + ], + }, + [ + { + type: 'index-pattern', + name: `xy-visualization-layer-annotation`, + id: 'indexPattern1', + }, + ] + ) + ).toEqual({ + ...baseState, + layers: [ + ...baseState.layers, + { + layerId: 'annotation', + layerType: layerTypes.ANNOTATIONS, + indexPatternId: 'indexPattern1', + annotations: [exampleAnnotation2], + }, + ], + }); + }); + + it('should fallback to the first dataView reference in case there are missing annotation references', () => { + const baseState = exampleState(); + expect( + xyVisualization.fromPersistableState!( + { + ...baseState, + layers: [ + ...baseState.layers, + { + layerId: 'annotation', + layerType: layerTypes.ANNOTATIONS, + annotations: [exampleAnnotation2], + }, + ], + }, + [ + { + type: 'index-pattern', + name: 'something-else', + id: 'indexPattern1', + }, + ] + ) + ).toEqual({ + ...baseState, + layers: [ + ...baseState.layers, + { + layerId: 'annotation', + layerType: layerTypes.ANNOTATIONS, + indexPatternId: 'indexPattern1', + annotations: [exampleAnnotation2], + }, + ], + }); + }); + }); }); diff --git a/x-pack/plugins/lens/public/visualizations/xy/visualization.tsx b/x-pack/plugins/lens/public/visualizations/xy/visualization.tsx index 24710c3261cdbe..4e9a2e55e19ad9 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/visualization.tsx +++ b/x-pack/plugins/lens/public/visualizations/xy/visualization.tsx @@ -14,7 +14,7 @@ import type { PaletteRegistry } from '@kbn/coloring'; import { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; import { CoreStart, ThemeServiceStart } from '@kbn/core/public'; import { EventAnnotationServiceType } from '@kbn/event-annotation-plugin/public'; -import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; +import { KibanaContextProvider, KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; import { VIS_EVENT_TO_TRIGGER } from '@kbn/visualizations-plugin/public'; import { FillStyle } from '@kbn/expression-xy-plugin/common'; import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; @@ -22,7 +22,7 @@ import type { IStorageWrapper } from '@kbn/kibana-utils-plugin/public'; import { getSuggestions } from './xy_suggestions'; import { XyToolbar } from './xy_config_panel'; import { DimensionEditor } from './xy_config_panel/dimension_editor'; -import { LayerHeader } from './xy_config_panel/layer_header'; +import { LayerHeader, LayerHeaderContent } from './xy_config_panel/layer_header'; import type { Visualization, AccessorConfig, FramePublicAPI } from '../../types'; import { State, @@ -33,9 +33,15 @@ import { YConfig, YAxisMode, SeriesType, + PersistedState, } from './types'; import { layerTypes } from '../../../common'; -import { isHorizontalChart } from './state_helpers'; +import { + extractReferences, + injectReferences, + isHorizontalChart, + validateColumn, +} from './state_helpers'; import { toExpression, toPreviewExpression, getSortedAccessors } from './to_expression'; import { getAccessorColorConfigs, getColorAssignments } from './color_assignment'; import { getColumnToLabelMap } from './state_helpers'; @@ -55,6 +61,7 @@ import { import { checkXAccessorCompatibility, defaultSeriesType, + getAnnotationsLayers, getAxisName, getDataLayers, getDescription, @@ -79,6 +86,7 @@ import { DimensionTrigger } from '../../shared_components/dimension_trigger'; import { defaultAnnotationLabel } from './annotations/helpers'; import { onDropForVisualization } from '../../editor_frame_service/editor_frame/config_panel/buttons/drop_targets_utils'; +const XY_ID = 'lnsXY'; export const getXyVisualization = ({ core, storage, @@ -97,8 +105,8 @@ export const getXyVisualization = ({ fieldFormats: FieldFormatsStart; useLegacyTimeAxis: boolean; kibanaTheme: ThemeServiceStart; -}): Visualization => ({ - id: 'lnsXY', +}): Visualization => ({ + id: XY_ID, visualizationTypes, getVisualizationTypeId(state) { const type = getVisualizationType(state); @@ -121,7 +129,7 @@ export const getXyVisualization = ({ }; }, - appendLayer(state, layerId, layerType) { + appendLayer(state, layerId, layerType, indexPatternId) { const firstUsedSeriesType = getDataLayers(state.layers)?.[0]?.seriesType; return { ...state, @@ -131,12 +139,13 @@ export const getXyVisualization = ({ seriesType: firstUsedSeriesType || state.preferredSeriesType, layerId, layerType, + indexPatternId, }), ], }; }, - clearLayer(state, layerId) { + clearLayer(state, layerId, indexPatternId) { return { ...state, layers: state.layers.map((l) => @@ -145,11 +154,20 @@ export const getXyVisualization = ({ : newLayerState({ seriesType: state.preferredSeriesType, layerId, + indexPatternId, }) ), }; }, + getPersistableState(state) { + return extractReferences(state); + }, + + fromPersistableState(state, references) { + return injectReferences(state, references); + }, + getDescription, switchVisualizationType(seriesType: string, state: State) { @@ -204,7 +222,7 @@ export const getXyVisualization = ({ return state; } const newLayers = [...state.layers]; - newLayers[layerIndex] = { ...layer }; + newLayers[layerIndex] = { ...layer, indexPatternId }; return { ...state, layers: newLayers, @@ -468,8 +486,10 @@ export const getXyVisualization = ({ return prevState; } if (isAnnotationsLayer(foundLayer)) { - const newLayer = { ...foundLayer }; - newLayer.annotations = newLayer.annotations.filter(({ id }) => id !== columnId); + const newLayer = { + ...foundLayer, + annotations: foundLayer.annotations.filter(({ id }) => id !== columnId), + }; const newLayers = prevState.layers.map((l) => (l.layerId === layerId ? newLayer : l)); return { @@ -520,6 +540,24 @@ export const getXyVisualization = ({ }; }, + renderLayerPanel(domElement, props) { + const { onChangeIndexPattern, ...otherProps } = props; + render( + + + { + // TODO: should it trigger an action as in the datasource? + onChangeIndexPattern(indexPatternId); + }} + /> + + , + domElement + ); + }, + renderLayerHeader(domElement, props) { render( @@ -560,7 +598,22 @@ export const getXyVisualization = ({ render( - {dimensionEditor} + + + {dimensionEditor} + + , domElement ); @@ -585,7 +638,53 @@ export const getXyVisualization = ({ eventAnnotationService ), - getErrorMessages(state, datasourceLayers) { + validateColumn(state, frame, layerId, columnId, group) { + const { invalid, invalidMessages } = validateColumn(state, frame, layerId, columnId, group); + if (!invalid) { + return { invalid }; + } + return { invalid, invalidMessage: invalidMessages![0] }; + }, + + getErrorMessages(state, frame) { + const { datasourceLayers, dataViews } = frame || {}; + const errors: Array<{ + shortMessage: string; + longMessage: React.ReactNode; + }> = []; + + const annotationLayers = getAnnotationsLayers(state.layers); + + if (dataViews) { + annotationLayers.forEach((layer) => { + layer.annotations.forEach((annotation) => { + const validatedColumn = validateColumn( + state, + { dataViews }, + layer.layerId, + annotation.id + ); + if (validatedColumn?.invalid && validatedColumn.invalidMessages?.length) { + errors.push( + ...validatedColumn.invalidMessages.map((invalidMessage) => ({ + shortMessage: invalidMessage, + longMessage: ( + + ), + })) + ); + } + }); + }); + } + // Data error handling below here const hasNoAccessors = ({ accessors }: XYDataLayerConfig) => accessors == null || accessors.length === 0; @@ -594,11 +693,6 @@ export const getXyVisualization = ({ const hasNoSplitAccessor = ({ splitAccessor, seriesType }: XYDataLayerConfig) => seriesType.includes('percentage') && splitAccessor == null; - const errors: Array<{ - shortMessage: string; - longMessage: React.ReactNode; - }> = []; - // check if the layers in the state are compatible with this type of chart if (state && state.layers.length > 1) { // Order is important here: Y Axis is fundamental to exist to make it valid @@ -696,6 +790,11 @@ export const getXyVisualization = ({ getUniqueLabels(state) { return getUniqueLabels(state.layers); }, + getUsedDataViews(state) { + return ( + state?.layers.filter(isAnnotationsLayer).map(({ indexPatternId }) => indexPatternId) ?? [] + ); + }, renderDimensionTrigger({ columnId, label, diff --git a/x-pack/plugins/lens/public/visualizations/xy/visualization_helpers.tsx b/x-pack/plugins/lens/public/visualizations/xy/visualization_helpers.tsx index 46bc1ba8dc551a..0e32e4006187cc 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/visualization_helpers.tsx +++ b/x-pack/plugins/lens/public/visualizations/xy/visualization_helpers.tsx @@ -275,10 +275,17 @@ const newLayerFn = { layerType: layerTypes.REFERENCELINE, accessors: [], }), - [layerTypes.ANNOTATIONS]: ({ layerId }: { layerId: string }): XYAnnotationLayerConfig => ({ + [layerTypes.ANNOTATIONS]: ({ + layerId, + indexPatternId, + }: { + layerId: string; + indexPatternId: string; + }): XYAnnotationLayerConfig => ({ layerId, layerType: layerTypes.ANNOTATIONS, annotations: [], + indexPatternId, }), }; @@ -286,12 +293,14 @@ export function newLayerState({ layerId, layerType = layerTypes.DATA, seriesType, + indexPatternId, }: { layerId: string; layerType?: LayerType; seriesType: SeriesType; + indexPatternId: string; }) { - return newLayerFn[layerType]({ layerId, seriesType }); + return newLayerFn[layerType]({ layerId, seriesType, indexPatternId }); } export function getLayersByType(state: State, byType?: string) { diff --git a/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/annotations_panel.tsx b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/annotations_panel.tsx index 5d5e4360b28f98..96f31e2e8754f0 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/annotations_panel.tsx +++ b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/annotations_panel.tsx @@ -8,121 +8,41 @@ import './index.scss'; import React, { useCallback } from 'react'; import { i18n } from '@kbn/i18n'; -import { - EuiDatePicker, - EuiFormRow, - EuiSwitch, - EuiSwitchEvent, - EuiButtonGroup, - EuiFormLabel, - EuiFormControlLayout, - EuiText, - transparentize, -} from '@elastic/eui'; +import { EuiFormRow, EuiSwitch, EuiSwitchEvent, EuiButtonGroup, EuiSpacer } from '@elastic/eui'; import type { PaletteRegistry } from '@kbn/coloring'; -import moment from 'moment'; -import { - EventAnnotationConfig, - PointInTimeEventAnnotationConfig, - RangeEventAnnotationConfig, -} from '@kbn/event-annotation-plugin/common/types'; -import { pick } from 'lodash'; import type { DatatableUtilitiesService } from '@kbn/data-plugin/common'; -import { search } from '@kbn/data-plugin/public'; import { defaultAnnotationColor, defaultAnnotationRangeColor, + isQueryAnnotationConfig, isRangeAnnotationConfig, - isManualPointAnnotationConfig, } from '@kbn/event-annotation-plugin/public'; -import Color from 'color'; -import { getDataLayers } from '../../visualization_helpers'; +import { QueryPointEventAnnotationConfig } from '@kbn/event-annotation-plugin/common'; +import { + FieldOption, + FieldOptionValue, + FieldPicker, +} from '../../../../shared_components/field_picker'; import { FormatFactory } from '../../../../../common'; -import { DONT_CLOSE_DIMENSION_CONTAINER_ON_CLICK_CLASS } from '../../../../utils'; import { DimensionEditorSection, + fieldExists, NameInput, useDebouncedValue, } from '../../../../shared_components'; import { isHorizontalChart } from '../../state_helpers'; -import { defaultAnnotationLabel, defaultRangeAnnotationLabel } from '../../annotations/helpers'; +import { defaultAnnotationLabel } from '../../annotations/helpers'; import { ColorPicker } from '../color_picker'; import { IconSelectSetting, TextDecorationSetting } from '../shared/marker_decoration_settings'; import { LineStyleSettings } from '../shared/line_style_settings'; import { updateLayer } from '..'; import { annotationsIconSet } from './icon_set'; -import type { FramePublicAPI, VisualizationDimensionEditorProps } from '../../../../types'; -import { State, XYState, XYAnnotationLayerConfig, XYDataLayerConfig } from '../../types'; - -export const toRangeAnnotationColor = (color = defaultAnnotationColor) => { - return new Color(transparentize(color, 0.1)).hexa(); -}; - -export const toLineAnnotationColor = (color = defaultAnnotationRangeColor) => { - return new Color(transparentize(color, 1)).hex(); -}; - -export const getEndTimestamp = ( - datatableUtilities: DatatableUtilitiesService, - startTime: string, - { activeData, dateRange }: FramePublicAPI, - dataLayers: XYDataLayerConfig[] -) => { - const startTimeNumber = moment(startTime).valueOf(); - const dateRangeFraction = - (moment(dateRange.toDate).valueOf() - moment(dateRange.fromDate).valueOf()) * 0.1; - const fallbackValue = moment(startTimeNumber + dateRangeFraction).toISOString(); - const dataLayersId = dataLayers.map(({ layerId }) => layerId); - if ( - !dataLayersId.length || - !activeData || - Object.entries(activeData) - .filter(([key]) => dataLayersId.includes(key)) - .every(([, { rows }]) => !rows || !rows.length) - ) { - return fallbackValue; - } - const xColumn = activeData?.[dataLayersId[0]].columns.find( - (column) => column.id === dataLayers[0].xAccessor - ); - if (!xColumn) { - return fallbackValue; - } - - const dateInterval = datatableUtilities.getDateHistogramMeta(xColumn)?.interval; - if (!dateInterval) return fallbackValue; - const intervalDuration = search.aggs.parseInterval(dateInterval); - if (!intervalDuration) return fallbackValue; - return moment(startTimeNumber + 3 * intervalDuration.as('milliseconds')).toISOString(); -}; - -const sanitizeProperties = (annotation: EventAnnotationConfig) => { - if (isRangeAnnotationConfig(annotation)) { - const rangeAnnotation: RangeEventAnnotationConfig = pick(annotation, [ - 'label', - 'key', - 'id', - 'isHidden', - 'color', - 'outside', - ]); - return rangeAnnotation; - } else if (isManualPointAnnotationConfig(annotation)) { - const lineAnnotation: PointInTimeEventAnnotationConfig = pick(annotation, [ - 'id', - 'label', - 'key', - 'isHidden', - 'lineStyle', - 'lineWidth', - 'color', - 'icon', - 'textVisibility', - ]); - return lineAnnotation; - } - return annotation; // todo: sanitize for the query annotations here -}; +import type { VisualizationDimensionEditorProps } from '../../../../types'; +import type { State, XYState, XYAnnotationLayerConfig } from '../../types'; +import { ConfigPanelManualAnnotation } from './manual_annotation_panel'; +import { ConfigPanelQueryAnnotation } from './query_annotation_panel'; +import { TooltipSection } from './tooltip_annotation_panel'; +import { sanitizeProperties } from './helpers'; export const AnnotationsPanel = ( props: VisualizationDimensionEditorProps & { @@ -146,8 +66,8 @@ export const AnnotationsPanel = ( const currentAnnotation = localLayer.annotations?.find((c) => c.id === accessor); + const isQueryBased = isQueryAnnotationConfig(currentAnnotation); const isRange = isRangeAnnotationConfig(currentAnnotation); - const isManualPoint = isManualPointAnnotationConfig(currentAnnotation); const setAnnotations = useCallback( (annotation) => { @@ -178,99 +98,69 @@ export const AnnotationsPanel = ( defaultMessage: 'Placement', })} > - {isRange ? ( - <> - { - if (date) { - const currentEndTime = moment(currentAnnotation?.key.endTimestamp).valueOf(); - if (currentEndTime < date.valueOf()) { - const currentStartTime = moment(currentAnnotation?.key.timestamp).valueOf(); - const dif = currentEndTime - currentStartTime; - setAnnotations({ - key: { - ...(currentAnnotation?.key || { type: 'range' }), - timestamp: date.toISOString(), - endTimestamp: moment(date.valueOf() + dif).toISOString(), - }, - }); - } else { - setAnnotations({ - key: { - ...(currentAnnotation?.key || { type: 'range' }), - timestamp: date.toISOString(), - }, - }); - } - } - }} - label={i18n.translate('xpack.lens.xyChart.annotationDate', { - defaultMessage: 'Annotation date', - })} - /> - { - if (date) { - const currentStartTime = moment(currentAnnotation?.key.timestamp).valueOf(); - if (currentStartTime > date.valueOf()) { - const currentEndTime = moment(currentAnnotation?.key.endTimestamp).valueOf(); - const dif = currentEndTime - currentStartTime; - setAnnotations({ - key: { - ...(currentAnnotation?.key || { type: 'range' }), - endTimestamp: date.toISOString(), - timestamp: moment(date.valueOf() - dif).toISOString(), - }, - }); - } else { - setAnnotations({ - key: { - ...(currentAnnotation?.key || { type: 'range' }), - endTimestamp: date.toISOString(), - }, - }); - } - } - }} - /> - - ) : isManualPoint ? ( - + { - if (date) { - setAnnotations({ - key: { - ...(currentAnnotation?.key || { type: 'point_in_time' }), - timestamp: date.toISOString(), - }, - }); - } + data-test-subj="lns-xyAnnotation-placementType" + name="placementType" + buttonSize="compressed" + options={[ + { + id: `lens_xyChart_annotation_staticDate`, + label: i18n.translate('xpack.lens.xyChart.annotation.staticDate', { + defaultMessage: 'Static Date', + }), + 'data-test-subj': 'lnsXY_annotation_staticDate', + }, + { + id: `lens_xyChart_annotation_query`, + label: i18n.translate('xpack.lens.xyChart.annotation.query', { + defaultMessage: 'Query', + }), + 'data-test-subj': 'lnsXY_annotation_query', + }, + ]} + idSelected={`lens_xyChart_annotation_${ + currentAnnotation?.type === 'query' ? 'query' : 'staticDate' + }`} + onChange={(id) => { + setAnnotations({ + type: id === `lens_xyChart_annotation_query` ? 'query' : 'manual', + // when switching to query, reset the key value + key: + !isQueryBased && id === `lens_xyChart_annotation_query` + ? { type: 'point_in_time' } + : currentAnnotation?.key, + }); }} + isFullWidth /> - ) : null} - - + + {isQueryBased ? ( + + ) : ( + + )} {!isRange && ( - - )} - {!isRange && ( - - )} - {!isRange && ( - - )} + <> + + + {(textDecorationSelected) => { + if (textDecorationSelected !== 'field') { + return null; + } + const currentIndexPattern = + frame.dataViews.indexPatterns[localLayer.indexPatternId]; + const options = currentIndexPattern.fields + .filter(({ displayName, type }) => displayName && type !== 'document') + .map( + (field) => + ({ + label: field.displayName, + value: { + type: 'field', + field: field.name, + dataType: field.type, + }, + exists: fieldExists( + frame.dataViews.existingFields[currentIndexPattern.title], + field.name + ), + compatible: true, + 'data-test-subj': `lnsXY-annotation-fieldOption-${field.name}`, + } as FieldOption) + ); + const selectedField = (currentAnnotation as QueryPointEventAnnotationConfig) + .textField; + const fieldIsValid = selectedField + ? Boolean(currentIndexPattern.getFieldByName(selectedField)) + : true; + return ( + <> + + + + ); + }} + + + + )} {isRange && ( setAnnotations({ isHidden: ev.target.checked })} /> - - ); -}; - -const ConfigPanelApplyAsRangeSwitch = ({ - annotation, - datatableUtilities, - onChange, - frame, - state, -}: { - annotation?: EventAnnotationConfig; - datatableUtilities: DatatableUtilitiesService; - onChange: (annotations: Partial | undefined) => void; - frame: FramePublicAPI; - state: XYState; -}) => { - const isRange = isRangeAnnotationConfig(annotation); - const isManualPoint = isManualPointAnnotationConfig(annotation); - return ( - - - {i18n.translate('xpack.lens.xyChart.applyAsRange', { - defaultMessage: 'Apply as range', - })} - - } - checked={isRange} - onChange={() => { - if (isRange) { - const newPointAnnotation: PointInTimeEventAnnotationConfig = { - key: { - type: 'point_in_time', - timestamp: annotation.key.timestamp, - }, - id: annotation.id, - label: - annotation.label === defaultRangeAnnotationLabel - ? defaultAnnotationLabel - : annotation.label, - color: toLineAnnotationColor(annotation.color), - isHidden: annotation.isHidden, - }; - onChange(newPointAnnotation); - } else if (isManualPoint) { - const fromTimestamp = moment(annotation?.key?.timestamp); - const dataLayers = getDataLayers(state.layers); - const newRangeAnnotation: RangeEventAnnotationConfig = { - key: { - type: 'range', - timestamp: annotation.key.timestamp, - endTimestamp: getEndTimestamp( - datatableUtilities, - fromTimestamp.toISOString(), - frame, - dataLayers - ), - }, - id: annotation.id, - label: - annotation.label === defaultAnnotationLabel - ? defaultRangeAnnotationLabel - : annotation.label, - color: toRangeAnnotationColor(annotation.color), - isHidden: annotation.isHidden, - }; - onChange(newRangeAnnotation); - } - }} - compressed - /> - - ); -}; - -const ConfigPanelRangeDatePicker = ({ - value, - label, - prependLabel, - onChange, - dataTestSubj = 'lnsXY_annotation_date_picker', -}: { - value: moment.Moment; - prependLabel?: string; - label?: string; - onChange: (val: moment.Moment | null) => void; - dataTestSubj?: string; -}) => { - return ( - - {prependLabel ? ( - {prependLabel} - } + {isQueryBased && currentAnnotation && ( + - - - ) : ( - + label={i18n.translate('xpack.lens.xyChart.annotation.tooltip', { + defaultMessage: 'Show additional fields', + })} + > + + + )} - + ); }; diff --git a/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/helpers.ts b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/helpers.ts new file mode 100644 index 00000000000000..2ca0f9530bbe1f --- /dev/null +++ b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/helpers.ts @@ -0,0 +1,116 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { search } from '@kbn/data-plugin/public'; +import { transparentize } from '@elastic/eui'; +import type { DatatableUtilitiesService } from '@kbn/data-plugin/common'; +import type { + EventAnnotationConfig, + RangeEventAnnotationConfig, + PointInTimeEventAnnotationConfig, + QueryPointEventAnnotationConfig, +} from '@kbn/event-annotation-plugin/common'; +import { + defaultAnnotationColor, + defaultAnnotationRangeColor, + isQueryAnnotationConfig, + isRangeAnnotationConfig, +} from '@kbn/event-annotation-plugin/public'; +import Color from 'color'; +import { pick } from 'lodash'; +import moment from 'moment'; +import type { FramePublicAPI } from '../../../../types'; +import type { XYDataLayerConfig } from '../../types'; + +export const toRangeAnnotationColor = (color = defaultAnnotationColor) => { + return new Color(transparentize(color, 0.1)).hexa(); +}; + +export const toLineAnnotationColor = (color = defaultAnnotationRangeColor) => { + return new Color(transparentize(color, 1)).hex(); +}; + +export const getEndTimestamp = ( + datatableUtilities: DatatableUtilitiesService, + startTime: string, + { activeData, dateRange }: FramePublicAPI, + dataLayers: XYDataLayerConfig[] +) => { + const startTimeNumber = moment(startTime).valueOf(); + const dateRangeFraction = + (moment(dateRange.toDate).valueOf() - moment(dateRange.fromDate).valueOf()) * 0.1; + const fallbackValue = moment(startTimeNumber + dateRangeFraction).toISOString(); + const dataLayersId = dataLayers.map(({ layerId }) => layerId); + if ( + !dataLayersId.length || + !activeData || + Object.entries(activeData) + .filter(([key]) => dataLayersId.includes(key)) + .every(([, { rows }]) => !rows || !rows.length) + ) { + return fallbackValue; + } + const xColumn = activeData?.[dataLayersId[0]].columns.find( + (column) => column.id === dataLayers[0].xAccessor + ); + if (!xColumn) { + return fallbackValue; + } + + const dateInterval = datatableUtilities.getDateHistogramMeta(xColumn)?.interval; + if (!dateInterval) return fallbackValue; + const intervalDuration = search.aggs.parseInterval(dateInterval); + if (!intervalDuration) return fallbackValue; + return moment(startTimeNumber + 3 * intervalDuration.as('milliseconds')).toISOString(); +}; + +export const sanitizeProperties = (annotation: EventAnnotationConfig) => { + if (isRangeAnnotationConfig(annotation)) { + const rangeAnnotation: RangeEventAnnotationConfig = pick(annotation, [ + 'type', + 'label', + 'key', + 'id', + 'isHidden', + 'color', + 'outside', + ]); + return rangeAnnotation; + } + if (isQueryAnnotationConfig(annotation)) { + const lineAnnotation: QueryPointEventAnnotationConfig = pick(annotation, [ + 'type', + 'id', + 'label', + 'key', + 'timeField', + 'isHidden', + 'lineStyle', + 'lineWidth', + 'color', + 'icon', + 'textVisibility', + 'textField', + 'filter', + 'extraFields', + ]); + return lineAnnotation; + } + const lineAnnotation: PointInTimeEventAnnotationConfig = pick(annotation, [ + 'type', + 'id', + 'label', + 'key', + 'isHidden', + 'lineStyle', + 'lineWidth', + 'color', + 'icon', + 'textVisibility', + ]); + return lineAnnotation; +}; diff --git a/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/index.test.tsx b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/index.test.tsx index 330fbf1f55da61..5514e3062213e0 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/index.test.tsx +++ b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/index.test.tsx @@ -16,6 +16,9 @@ import { State } from '../../types'; import { Position } from '@elastic/charts'; import { chartPluginMock } from '@kbn/charts-plugin/public/mocks'; import moment from 'moment'; +import { EventAnnotationConfig } from '@kbn/event-annotation-plugin/common'; +import { createMockDataViewsState } from '../../../../data_views_service/mocks'; +import { createMockedIndexPattern } from '../../../../indexpattern_datasource/mocks'; jest.mock('lodash', () => { const original = jest.requireActual('lodash'); @@ -26,8 +29,9 @@ jest.mock('lodash', () => { }; }); -const customLineStaticAnnotation = { +const customLineStaticAnnotation: EventAnnotationConfig = { id: 'ann1', + type: 'manual', key: { type: 'point_in_time' as const, timestamp: '2022-03-18T08:25:00.000Z' }, label: 'Event', icon: 'triangle' as const, @@ -49,6 +53,7 @@ describe('AnnotationsPanel', () => { { layerType: layerTypes.ANNOTATIONS, layerId: 'annotation', + indexPatternId: 'indexPattern1', annotations: [customLineStaticAnnotation], }, ], @@ -56,9 +61,9 @@ describe('AnnotationsPanel', () => { } beforeEach(() => { - frame = createMockFramePublicAPI(); - frame.datasourceLayers = {}; + frame = createMockFramePublicAPI({ datasourceLayers: {} }); }); + describe('Dimension Editor', () => { test('shows correct options for line annotations', () => { const state = testState(); @@ -109,6 +114,7 @@ describe('AnnotationsPanel', () => { color: 'red', icon: 'triangle', id: 'ann1', + type: 'manual', isHidden: undefined, key: { endTimestamp: '2022-03-21T10:49:00.000Z', @@ -122,6 +128,7 @@ describe('AnnotationsPanel', () => { ], layerId: 'annotation', layerType: 'annotations', + indexPatternId: 'indexPattern1', }; const component = mount( { panelRef={React.createRef()} /> ); + component.find('button[data-test-subj="lns-xyAnnotation-rangeSwitch"]').simulate('click'); expect(setState).toBeCalledWith({ @@ -188,6 +196,7 @@ describe('AnnotationsPanel', () => { id: 'ann1', isHidden: undefined, label: 'Event range', + type: 'manual', key: { endTimestamp: '2022-03-21T10:49:00.000Z', timestamp: '2022-03-18T08:25:00.000Z', @@ -195,6 +204,7 @@ describe('AnnotationsPanel', () => { }, }, ], + indexPatternId: 'indexPattern1', layerId: 'annotation', layerType: 'annotations', }, @@ -215,13 +225,85 @@ describe('AnnotationsPanel', () => { type: 'point_in_time', }, label: 'Event', + type: 'manual', }, ], + indexPatternId: 'indexPattern1', layerId: 'annotation', layerType: 'annotations', }, ], }); }); + + test('shows correct options for query based', () => { + const state = testState(); + const indexPattern = createMockedIndexPattern(); + state.layers[0] = { + annotations: [ + { + color: 'red', + icon: 'triangle', + id: 'ann1', + type: 'query', + isHidden: undefined, + timeField: 'timestamp', + key: { + type: 'point_in_time', + }, + label: 'Query based event', + lineStyle: 'dashed', + lineWidth: 3, + filter: { type: 'kibana_query', query: '', language: 'kuery' }, + }, + ], + layerId: 'annotation', + layerType: 'annotations', + indexPatternId: indexPattern.id, + }; + const frameMock = createMockFramePublicAPI({ + datasourceLayers: {}, + dataViews: createMockDataViewsState({ + indexPatterns: { [indexPattern.id]: indexPattern }, + }), + }); + + const component = mount( + + ); + + expect( + component.find('[data-test-subj="annotation-query-based-field-picker"]').exists() + ).toBeTruthy(); + expect( + component.find('[data-test-subj="annotation-query-based-query-input"]').exists() + ).toBeTruthy(); + + // The provided indexPattern has 2 date fields + expect( + component + .find('[data-test-subj="annotation-query-based-field-picker"]') + .at(0) + .prop('options') + ).toHaveLength(2); + // When in query mode a new "field" option is added to the previous 2 ones + expect( + component.find('[data-test-subj="lns-lineMarker-text-visibility"]').at(0).prop('options') + ).toHaveLength(3); + expect( + component.find('[data-test-subj="lnsXY-annotation-tooltip-add_field"]').exists() + ).toBeTruthy(); + }); }); }); diff --git a/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/manual_annotation_panel.tsx b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/manual_annotation_panel.tsx new file mode 100644 index 00000000000000..33b04b17b1a2fd --- /dev/null +++ b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/manual_annotation_panel.tsx @@ -0,0 +1,131 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { DatatableUtilitiesService } from '@kbn/data-plugin/common'; +import { isRangeAnnotationConfig } from '@kbn/event-annotation-plugin/public'; +import { i18n } from '@kbn/i18n'; +import moment from 'moment'; +import React from 'react'; +import type { FramePublicAPI } from '../../../../types'; +import type { XYState } from '../../types'; +import { + ConfigPanelRangeDatePicker, + ConfigPanelApplyAsRangeSwitch, +} from './range_annotation_panel'; +import type { ManualEventAnnotationType } from './types'; + +export const ConfigPanelManualAnnotation = ({ + annotation, + frame, + state, + onChange, + datatableUtilities, +}: { + annotation?: ManualEventAnnotationType | undefined; + onChange: (annotations: Partial | undefined) => void; + datatableUtilities: DatatableUtilitiesService; + frame: FramePublicAPI; + state: XYState; +}) => { + const isRange = isRangeAnnotationConfig(annotation); + return ( + <> + {isRange ? ( + <> + { + if (date) { + const currentEndTime = moment(annotation?.key.endTimestamp).valueOf(); + if (currentEndTime < date.valueOf()) { + const currentStartTime = moment(annotation?.key.timestamp).valueOf(); + const dif = currentEndTime - currentStartTime; + onChange({ + key: { + ...(annotation?.key || { type: 'range' }), + timestamp: date.toISOString(), + endTimestamp: moment(date.valueOf() + dif).toISOString(), + }, + }); + } else { + onChange({ + key: { + ...(annotation?.key || { type: 'range' }), + timestamp: date.toISOString(), + }, + }); + } + } + }} + label={i18n.translate('xpack.lens.xyChart.annotationDate', { + defaultMessage: 'Annotation date', + })} + /> + { + if (date) { + const currentStartTime = moment(annotation?.key.timestamp).valueOf(); + if (currentStartTime > date.valueOf()) { + const currentEndTime = moment(annotation?.key.endTimestamp).valueOf(); + const dif = currentEndTime - currentStartTime; + onChange({ + key: { + ...(annotation?.key || { type: 'range' }), + endTimestamp: date.toISOString(), + timestamp: moment(date.valueOf() - dif).toISOString(), + }, + }); + } else { + onChange({ + key: { + ...(annotation?.key || { type: 'range' }), + endTimestamp: date.toISOString(), + }, + }); + } + } + }} + /> + + ) : ( + { + if (date) { + onChange({ + key: { + ...(annotation?.key || { type: 'point_in_time' }), + timestamp: date.toISOString(), + }, + }); + } + }} + /> + )} + + + ); +}; diff --git a/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/query_annotation_panel.tsx b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/query_annotation_panel.tsx new file mode 100644 index 00000000000000..c9cd0bbec7d350 --- /dev/null +++ b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/query_annotation_panel.tsx @@ -0,0 +1,137 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { EuiFormRow } from '@elastic/eui'; +import type { Query } from '@kbn/data-plugin/common'; +import type { QueryPointEventAnnotationConfig } from '@kbn/event-annotation-plugin/common'; +import { i18n } from '@kbn/i18n'; +import React from 'react'; +import { + fieldExists, + FieldOption, + FieldOptionValue, + FieldPicker, + QueryInput, + validateQuery, +} from '../../../../shared_components'; +import type { FramePublicAPI } from '../../../../types'; +import type { XYState, XYAnnotationLayerConfig } from '../../types'; + +export const defaultQuery: Query = { + query: '', + language: 'kuery', +}; + +export const ConfigPanelQueryAnnotation = ({ + annotation, + frame, + state, + onChange, + layer, +}: { + annotation?: QueryPointEventAnnotationConfig; + onChange: (annotations: Partial | undefined) => void; + frame: FramePublicAPI; + state: XYState; + layer: XYAnnotationLayerConfig; +}) => { + const inputQuery = annotation?.filter ?? defaultQuery; + const currentIndexPattern = frame.dataViews.indexPatterns[layer.indexPatternId]; + const currentExistingFields = frame.dataViews.existingFields[currentIndexPattern.title]; + // list only supported field by operation, remove the rest + const options = currentIndexPattern.fields + .filter((field) => field.type === 'date' && field.displayName) + .map((field) => { + return { + label: field.displayName, + value: { + type: 'field', + field: field.name, + dataType: field.type, + }, + exists: fieldExists(currentExistingFields, field.name), + compatible: true, + 'data-test-subj': `lns-fieldOption-${field.name}`, + } as FieldOption; + }); + const { isValid: isQueryInputValid, error: queryInputError } = validateQuery( + annotation?.filter, + currentIndexPattern + ); + + const selectedField = + annotation?.timeField || currentIndexPattern.timeFieldName || options[0]?.value.field; + const fieldIsValid = selectedField + ? Boolean(currentIndexPattern.getFieldByName(selectedField)) + : true; + return ( + <> + + {}} + data-test-subj="annotation-query-based-query-input" + placeholder={ + inputQuery.language === 'kuery' + ? i18n.translate('xpack.lens.annotations.query.queryPlaceholderKql', { + defaultMessage: '{example}', + values: { example: 'method : "GET"' }, + }) + : i18n.translate('xpack.lens.annotations.query.queryPlaceholderLucene', { + defaultMessage: '{example}', + values: { example: 'method:GET' }, + }) + } + /> + + + + + + ); +}; diff --git a/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/range_annotation_panel.tsx b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/range_annotation_panel.tsx new file mode 100644 index 00000000000000..edecd94e3c8e85 --- /dev/null +++ b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/range_annotation_panel.tsx @@ -0,0 +1,154 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { DatatableUtilitiesService } from '@kbn/data-plugin/common'; +import type { + PointInTimeEventAnnotationConfig, + RangeEventAnnotationConfig, +} from '@kbn/event-annotation-plugin/common'; +import { isRangeAnnotationConfig } from '@kbn/event-annotation-plugin/public'; +import { i18n } from '@kbn/i18n'; +import React from 'react'; +import { + EuiFormRow, + EuiSwitch, + EuiText, + EuiFormControlLayout, + EuiFormLabel, + EuiDatePicker, +} from '@elastic/eui'; +import moment from 'moment'; +import { DONT_CLOSE_DIMENSION_CONTAINER_ON_CLICK_CLASS } from '../../../../utils'; +import type { FramePublicAPI } from '../../../../types'; +import { defaultRangeAnnotationLabel, defaultAnnotationLabel } from '../../annotations/helpers'; +import type { XYState } from '../../types'; +import { getDataLayers } from '../../visualization_helpers'; +import { toLineAnnotationColor, getEndTimestamp, toRangeAnnotationColor } from './helpers'; +import type { ManualEventAnnotationType } from './types'; + +export const ConfigPanelApplyAsRangeSwitch = ({ + annotation, + datatableUtilities, + onChange, + frame, + state, +}: { + annotation?: ManualEventAnnotationType; + datatableUtilities: DatatableUtilitiesService; + onChange: (annotations: Partial | undefined) => void; + frame: FramePublicAPI; + state: XYState; +}) => { + const isRange = isRangeAnnotationConfig(annotation); + return ( + + + {i18n.translate('xpack.lens.xyChart.applyAsRange', { + defaultMessage: 'Apply as range', + })} + + } + checked={isRange} + onChange={() => { + if (isRange) { + const newPointAnnotation: PointInTimeEventAnnotationConfig = { + type: 'manual', + key: { + type: 'point_in_time', + timestamp: annotation.key.timestamp, + }, + id: annotation.id, + label: + annotation.label === defaultRangeAnnotationLabel + ? defaultAnnotationLabel + : annotation.label, + color: toLineAnnotationColor(annotation.color), + isHidden: annotation.isHidden, + }; + onChange(newPointAnnotation); + } else if (annotation) { + const fromTimestamp = moment(annotation?.key.timestamp); + const dataLayers = getDataLayers(state.layers); + const newRangeAnnotation: RangeEventAnnotationConfig = { + type: 'manual', + key: { + type: 'range', + timestamp: annotation.key.timestamp, + endTimestamp: getEndTimestamp( + datatableUtilities, + fromTimestamp.toISOString(), + frame, + dataLayers + ), + }, + id: annotation.id, + label: + annotation.label === defaultAnnotationLabel + ? defaultRangeAnnotationLabel + : annotation.label, + color: toRangeAnnotationColor(annotation.color), + isHidden: annotation.isHidden, + }; + onChange(newRangeAnnotation); + } + }} + compressed + /> + + ); +}; + +export const ConfigPanelRangeDatePicker = ({ + value, + label, + prependLabel, + onChange, + dataTestSubj = 'lnsXY_annotation_date_picker', +}: { + value: moment.Moment; + prependLabel?: string; + label?: string; + onChange: (val: moment.Moment | null) => void; + dataTestSubj?: string; +}) => { + return ( + + {prependLabel ? ( + {prependLabel} + } + > + + + ) : ( + + )} + + ); +}; diff --git a/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/tooltip_annotation_panel.tsx b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/tooltip_annotation_panel.tsx new file mode 100644 index 00000000000000..e4945f42f8089e --- /dev/null +++ b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/tooltip_annotation_panel.tsx @@ -0,0 +1,232 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + htmlIdGenerator, + EuiButton, + EuiButtonIcon, + EuiDraggable, + EuiFlexGroup, + EuiFlexItem, + EuiIcon, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import React, { useCallback, useMemo } from 'react'; +import { QueryPointEventAnnotationConfig } from '@kbn/event-annotation-plugin/common'; +import type { ExistingFieldsMap, IndexPattern } from '../../../../types'; +import { + fieldExists, + FieldOption, + FieldOptionValue, + FieldPicker, + useDebouncedValue, + NewBucketButton, + DragDropBuckets, +} from '../../../../shared_components'; + +const generateId = htmlIdGenerator(); +const supportedTypes = new Set(['string', 'boolean', 'number', 'ip', 'date']); + +export interface FieldInputsProps { + currentConfig: QueryPointEventAnnotationConfig; + setConfig: (config: QueryPointEventAnnotationConfig) => void; + indexPattern: IndexPattern; + existingFields: ExistingFieldsMap; + invalidFields?: string[]; +} + +interface WrappedValue { + id: string; + value: string | undefined; + isNew?: boolean; +} + +type SafeWrappedValue = Omit & { value: string }; + +function removeNewEmptyField(v: WrappedValue): v is SafeWrappedValue { + return v.value != null; +} + +export function TooltipSection({ + currentConfig, + setConfig, + indexPattern, + existingFields, + invalidFields, +}: FieldInputsProps) { + const onChangeWrapped = useCallback( + (values: WrappedValue[]) => { + setConfig({ + ...currentConfig, + extraFields: values.filter(removeNewEmptyField).map(({ value }) => value), + }); + }, + [setConfig, currentConfig] + ); + const { wrappedValues, rawValuesLookup } = useMemo(() => { + const rawValues = currentConfig.extraFields ?? []; + return { + wrappedValues: rawValues.map((value) => ({ id: generateId(), value })), + rawValuesLookup: new Set(rawValues), + }; + }, [currentConfig]); + + const { inputValue: localValues, handleInputChange } = useDebouncedValue({ + onChange: onChangeWrapped, + value: wrappedValues, + }); + + const onFieldSelectChange = useCallback( + (choice, index = 0) => { + const fields = [...localValues]; + + if (indexPattern.getFieldByName(choice.field)) { + fields[index] = { id: generateId(), value: choice.field }; + + // update the layer state + handleInputChange(fields); + } + }, + [localValues, indexPattern, handleInputChange] + ); + + const newBucketButton = ( + { + handleInputChange([...localValues, { id: generateId(), value: undefined, isNew: true }]); + }} + label={i18n.translate('xpack.lens.xyChart.annotation.tooltip.addField', { + defaultMessage: 'Add field', + })} + /> + ); + + if (localValues.length === 0) { + return ( + <> + + {}}> + {i18n.translate('xpack.lens.xyChart.annotation.tooltip.noFields', { + defaultMessage: 'None selected', + })} + + + {newBucketButton} + + ); + } + const currentExistingField = existingFields[indexPattern.title]; + const disableActions = localValues.length === 2 && localValues.some(({ isNew }) => isNew); + const options = indexPattern.fields + .filter( + ({ displayName, type }) => + displayName && !rawValuesLookup.has(displayName) && supportedTypes.has(type) + ) + .map( + (field) => + ({ + label: field.displayName, + value: { + type: 'field', + field: field.name, + dataType: field.type, + }, + exists: fieldExists(currentExistingField, field.name), + compatible: true, + 'data-test-subj': `lnsXY-annotation-tooltip-fieldOption-${field.name}`, + } as FieldOption) + ) + .sort((a, b) => a.label.localeCompare(b.label)); + + return ( + <> + { + handleInputChange(updatedValues); + }} + onDragStart={() => {}} + droppableId="ANNOTATION_TOOLTIP_DROPPABLE_AREA" + items={localValues} + > + {localValues.map(({ id, value, isNew }, index) => { + const fieldIsValid = value ? Boolean(indexPattern.getFieldByName(value)) : true; + return ( + + {(provided) => ( + + {/* Empty for spacing */} + + + + + + + + { + handleInputChange(localValues.filter((_, i) => i !== index)); + }} + data-test-subj={`lnsXY-annotation-tooltip-removeField-${index}`} + isDisabled={disableActions && !isNew} + /> + + + )} + + ); + })} + + {newBucketButton} + + ); +} diff --git a/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/types.ts b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/types.ts new file mode 100644 index 00000000000000..f446afb6be265e --- /dev/null +++ b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/types.ts @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + PointInTimeEventAnnotationConfig, + RangeEventAnnotationConfig, +} from '@kbn/event-annotation-plugin/common'; + +export type ManualEventAnnotationType = + | PointInTimeEventAnnotationConfig + | RangeEventAnnotationConfig; diff --git a/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/layer_header.tsx b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/layer_header.tsx index d55aa0aa121332..819dfe13c2ba21 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/layer_header.tsx +++ b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/layer_header.tsx @@ -10,10 +10,14 @@ import { i18n } from '@kbn/i18n'; import { EuiIcon, EuiPopover, EuiSelectable, EuiText, EuiPopoverTitle } from '@elastic/eui'; import { ToolbarButton } from '@kbn/kibana-react-plugin/public'; import { IconChartBarReferenceLine, IconChartBarAnnotations } from '@kbn/chart-icons'; -import type { VisualizationLayerWidgetProps, VisualizationType } from '../../../types'; -import { State, visualizationTypes, SeriesType } from '../types'; +import type { + VisualizationLayerHeaderContentProps, + VisualizationLayerWidgetProps, + VisualizationType, +} from '../../../types'; +import { State, visualizationTypes, SeriesType, XYAnnotationLayerConfig } from '../types'; import { isHorizontalChart, isHorizontalSeries } from '../state_helpers'; -import { StaticHeader } from '../../../shared_components'; +import { ChangeIndexPattern, StaticHeader } from '../../../shared_components'; import { updateLayer } from '.'; import { isAnnotationsLayer, isDataLayer, isReferenceLayer } from '../visualization_helpers'; @@ -24,12 +28,21 @@ export function LayerHeader(props: VisualizationLayerWidgetProps) { } if (isReferenceLayer(layer)) { return ; - } else if (isAnnotationsLayer(layer)) { + } + if (isAnnotationsLayer(layer)) { return ; } return ; } +export function LayerHeaderContent(props: VisualizationLayerHeaderContentProps) { + const layer = props.state.layers.find((l) => l.layerId === props.layerId); + if (layer && isAnnotationsLayer(layer)) { + return ; + } + return null; +} + function ReferenceLayerHeader() { return ( ) { + const notFoundTitleLabel = i18n.translate('xpack.lens.layerPanel.missingDataView', { + defaultMessage: 'Data view not found', + }); + const layerIndex = state.layers.findIndex((l) => l.layerId === layerId); + const layer = state.layers[layerIndex] as XYAnnotationLayerConfig; + const currentIndexPattern = frame.dataViews.indexPatterns[layer.indexPatternId]; + + return ( + + ); +} + function DataLayerHeader(props: VisualizationLayerWidgetProps) { const [isPopoverOpen, setPopoverIsOpen] = useState(false); const { state, layerId } = props; diff --git a/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/shared/marker_decoration_settings.tsx b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/shared/marker_decoration_settings.tsx index e11c69f766a328..b347a39c788cea 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/shared/marker_decoration_settings.tsx +++ b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/shared/marker_decoration_settings.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React from 'react'; +import React, { useState } from 'react'; import { i18n } from '@kbn/i18n'; import { EuiButtonGroup, EuiFormRow } from '@elastic/eui'; import { IconPosition } from '@kbn/expression-xy-plugin/common'; @@ -77,17 +77,67 @@ export interface MarkerDecorationConfig { icon?: T; iconPosition?: IconPosition; textVisibility?: boolean; + textField?: string; +} + +function getSelectedOption( + { textField, textVisibility }: MarkerDecorationConfig = {}, + isQueryBased?: boolean +) { + if (!textVisibility) { + return 'none'; + } + if (isQueryBased && textField) { + return 'field'; + } + return 'name'; } export function TextDecorationSetting({ currentConfig, setConfig, customIconSet, + isQueryBased, + children, }: { currentConfig?: MarkerDecorationConfig; setConfig: (config: MarkerDecorationConfig) => void; customIconSet?: IconSet; + isQueryBased?: boolean; + /** A children render function for custom sub fields on textDecoration change */ + children?: (textDecoration: 'none' | 'name' | 'field') => JSX.Element | null; }) { + // To model the temporary state for label based on field when user didn't pick up the field yet, + // use a local state + const [selectedVisibleOption, setVisibleOption] = useState<'none' | 'name' | 'field'>( + getSelectedOption(currentConfig, isQueryBased) + ); + const options = [ + { + id: `${idPrefix}none`, + label: i18n.translate('xpack.lens.xyChart.lineMarker.textVisibility.none', { + defaultMessage: 'None', + }), + 'data-test-subj': 'lnsXY_textVisibility_none', + }, + { + id: `${idPrefix}name`, + label: i18n.translate('xpack.lens.xyChart.lineMarker.textVisibility.name', { + defaultMessage: 'Name', + }), + 'data-test-subj': 'lnsXY_textVisibility_name', + }, + ]; + if (isQueryBased) { + options.push({ + id: `${idPrefix}field`, + label: i18n.translate('xpack.lens.xyChart.lineMarker.textVisibility.field', { + defaultMessage: 'Field', + }), + 'data-test-subj': 'lnsXY_textVisibility_field', + }); + } + return ( ({ display="columnCompressed" fullWidth > - { - setConfig({ textVisibility: id === `${idPrefix}name` }); - }} - isFullWidth - /> +
+ { + const chosenOption = id.replace(idPrefix, '') as 'none' | 'name' | 'field'; + if (chosenOption === 'none') { + setConfig({ + textVisibility: false, + textField: undefined, + }); + } else if (chosenOption === 'field') { + setConfig({ + textVisibility: true, + }); + } else if (chosenOption === 'name') { + setConfig({ + textVisibility: true, + textField: undefined, + }); + } + + setVisibleOption(chosenOption); + }} + isFullWidth + /> + {children?.(selectedVisibleOption)} +
); } diff --git a/x-pack/plugins/lens/public/visualizations/xy/xy_suggestions.test.ts b/x-pack/plugins/lens/public/visualizations/xy/xy_suggestions.test.ts index 676d1a0dafe294..a2a0463a41cc40 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/xy_suggestions.test.ts +++ b/x-pack/plugins/lens/public/visualizations/xy/xy_suggestions.test.ts @@ -549,9 +549,11 @@ describe('xy_suggestions', () => { const annotationLayer: XYAnnotationLayerConfig = { layerId: 'second', layerType: layerTypes.ANNOTATIONS, + indexPatternId: 'indexPattern1', annotations: [ { id: '1', + type: 'manual', key: { type: 'point_in_time', timestamp: '2020-20-22', diff --git a/x-pack/plugins/lens/server/embeddable/make_lens_embeddable_factory.ts b/x-pack/plugins/lens/server/embeddable/make_lens_embeddable_factory.ts index 8ae71538562ed9..bbac9821500004 100644 --- a/x-pack/plugins/lens/server/embeddable/make_lens_embeddable_factory.ts +++ b/x-pack/plugins/lens/server/embeddable/make_lens_embeddable_factory.ts @@ -27,6 +27,7 @@ import { commonUpdateVisLayerType, getLensCustomVisualizationMigrations, getLensFilterMigrations, + commonExplicitAnnotationType, getLensDataViewMigrations, commonMigrateMetricIds, commonMigratePartitionChartGroups, @@ -36,13 +37,14 @@ import { LensDocShape713, LensDocShape715, LensDocShape810, - LensDocShape840, + LensDocShape850, LensDocShapePre712, VisState716, VisState810, - VisState840, + VisState850, VisStatePre715, VisStatePre830, + XYVisState850, } from '../migrations/types'; import { extract, inject } from '../../common/embeddable_factory'; @@ -134,10 +136,16 @@ export const makeLensEmbeddableFactory = } as unknown as SerializableRecord; }, '8.5.0': (state) => { - const lensState = state as unknown as { attributes: LensDocShape840 }; + const lensState = state as unknown as { + attributes: LensDocShape850; + }; + let migratedLensState = commonMigrateMetricIds(lensState.attributes); + migratedLensState = commonExplicitAnnotationType( + migratedLensState as LensDocShape850 + ); migratedLensState = commonMigratePartitionChartGroups( - migratedLensState as LensDocShape840<{ + migratedLensState as LensDocShape850<{ shape: string; layers: Array<{ groups?: string[] }>; }> diff --git a/x-pack/plugins/lens/server/migrations/common_migrations.ts b/x-pack/plugins/lens/server/migrations/common_migrations.ts index b14fe7a3fa8fd1..89dca4829c583c 100644 --- a/x-pack/plugins/lens/server/migrations/common_migrations.ts +++ b/x-pack/plugins/lens/server/migrations/common_migrations.ts @@ -30,7 +30,8 @@ import { LensDocShape810, LensDocShape830, VisStatePre830, - LensDocShape840, + XYVisStatePre850, + VisState850, LensDocShape850, } from './types'; import { DOCUMENT_FIELD_NAME, layerTypes, LegacyMetricState, isPartitionShape } from '../../common'; @@ -422,16 +423,49 @@ export const commonFixValueLabelsInXY = ( }; }; +export const commonExplicitAnnotationType = ( + attributes: LensDocShape850 +): LensDocShape850 => { + // Skip the migration heavy part if not XY or it does not contain annotations + if ( + attributes.visualizationType !== 'lnsXY' || + attributes.state.visualization.layers.every((l) => l.layerType !== 'annotations') + ) { + return attributes as LensDocShape850; + } + const newAttributes = cloneDeep(attributes); + const { visualization } = newAttributes.state; + const { layers } = visualization; + return { + ...newAttributes, + state: { + ...newAttributes.state, + visualization: { + ...visualization, + layers: layers.map((l) => { + if (l.layerType !== 'annotations') { + return l; + } + return { + ...l, + annotations: l.annotations.map((a) => ({ ...a, type: 'manual' })), + }; + }), + }, + }, + }; +}; + export const commonMigrateMetricIds = ( - attributes: LensDocShape840 -): LensDocShape840 => { + attributes: LensDocShape850 +): LensDocShape850 => { const typeMappings = { lnsMetric: 'lnsLegacyMetric', lnsMetricNew: 'lnsMetric', } as Record; if (!attributes.visualizationType || !(attributes.visualizationType in typeMappings)) { - return attributes as LensDocShape840; + return attributes as LensDocShape850; } const newAttributes = cloneDeep(attributes); @@ -441,7 +475,7 @@ export const commonMigrateMetricIds = ( }; export const commonMigratePartitionChartGroups = ( - attributes: LensDocShape840<{ + attributes: LensDocShape850<{ shape: string; layers: Array<{ groups?: string[] }>; }> diff --git a/x-pack/plugins/lens/server/migrations/saved_object_migrations.test.ts b/x-pack/plugins/lens/server/migrations/saved_object_migrations.test.ts index 3f60eddb73e8e9..b07f801e53f117 100644 --- a/x-pack/plugins/lens/server/migrations/saved_object_migrations.test.ts +++ b/x-pack/plugins/lens/server/migrations/saved_object_migrations.test.ts @@ -22,6 +22,9 @@ import { VisState810, VisState820, VisState830, + LensDocShape850, + XYVisStatePre850, + VisState850, } from './types'; import { layerTypes, LegacyMetricState } from '../../common'; import { Filter } from '@kbn/es-query'; @@ -2291,6 +2294,44 @@ describe('Lens migrations', () => { }); }); + describe('8.5.0 Add Annotation event type and dataView references', () => { + const context = { log: { warn: () => {} } } as unknown as SavedObjectMigrationContext; + const example = { + type: 'lens', + id: 'mocked-saved-object-id', + attributes: { + savedObjectId: '1', + title: 'MyRenamedOps', + description: '', + visualizationType: 'lnsXY', + state: { + visualization: { + layers: [ + { layerType: 'data' }, + { + layerType: 'annotations', + annotations: [{ id: 'annotation-id' }], + }, + ], + }, + }, + }, + } as unknown as SavedObjectUnsanitizedDoc>; + + it('migrates existing annotation events as manual type', () => { + const result = migrations['8.5.0'](example, context) as ReturnType< + SavedObjectMigrationFn + >; + const visState = result.attributes.state.visualization as VisState850; + const [dataLayer, annotationLayer] = visState.layers; + expect(dataLayer).toEqual({ layerType: 'data' }); + expect(annotationLayer).toEqual({ + layerType: 'annotations', + annotations: [{ id: 'annotation-id', type: 'manual' }], + }); + }); + }); + describe('8.5.0 migrates metric IDs', () => { const context = { log: { warn: () => {} } } as unknown as SavedObjectMigrationContext; const example = { diff --git a/x-pack/plugins/lens/server/migrations/saved_object_migrations.ts b/x-pack/plugins/lens/server/migrations/saved_object_migrations.ts index 0dd3474b139d8f..e48f46ad885c50 100644 --- a/x-pack/plugins/lens/server/migrations/saved_object_migrations.ts +++ b/x-pack/plugins/lens/server/migrations/saved_object_migrations.ts @@ -34,7 +34,10 @@ import { XYVisualizationState830, VisState810, VisState820, + XYVisStatePre850, + LensDocShape850, LensDocShape840, + VisState850, } from './types'; import { commonRenameOperationsForFormula, @@ -52,6 +55,7 @@ import { commonFixValueLabelsInXY, commonLockOldMetricVisSettings, commonPreserveOldLegendSizeDefault, + commonExplicitAnnotationType, getLensDataViewMigrations, commonMigrateMetricIds, commonMigratePartitionChartGroups, @@ -516,7 +520,15 @@ const preserveOldLegendSizeDefault: SavedObjectMigrationFn ({ ...doc, attributes: commonPreserveOldLegendSizeDefault(doc.attributes) }); -const migrateMetricIds: SavedObjectMigrationFn = (doc) => ({ +const addEventAnnotationType: SavedObjectMigrationFn< + LensDocShape850, + LensDocShape850 +> = (doc) => { + const newDoc = cloneDeep(doc); + return { ...newDoc, attributes: commonExplicitAnnotationType(newDoc.attributes) }; +}; + +const migrateMetricIds: SavedObjectMigrationFn = (doc) => ({ ...doc, attributes: commonMigrateMetricIds(doc.attributes), }); @@ -553,7 +565,7 @@ const lensMigrations: SavedObjectMigrationMap = { enhanceTableRowHeight ), '8.3.0': flow(lockOldMetricVisSettings, preserveOldLegendSizeDefault, fixValueLabelsInXY), - '8.5.0': flow(migrateMetricIds, migratePartitionChartGroups), + '8.5.0': flow(migrateMetricIds, addEventAnnotationType, migratePartitionChartGroups), }; export const getAllMigrations = ( diff --git a/x-pack/plugins/lens/server/migrations/types.ts b/x-pack/plugins/lens/server/migrations/types.ts index 71dae1619db593..a922223b6ccd79 100644 --- a/x-pack/plugins/lens/server/migrations/types.ts +++ b/x-pack/plugins/lens/server/migrations/types.ts @@ -270,6 +270,34 @@ export interface XYVisualizationState830 extends VisState820 { export type VisStatePre830 = XYVisualizationStatePre830; export type VisState830 = XYVisualizationState830; +export interface XYVisStatePre850 { + layers: Array< + | { + layerId: string; + layerType: Exclude; + } + | { + layerId: string; + layerType: Extract; + annotations: Array<{ id: string }>; + } + >; +} + +export interface XYVisState850 { + layers: Array< + | { + layerId: string; + layerType: Exclude; + } + | { + layerId: string; + layerType: Extract; + annotations: Array<{ id: string; type: 'manual' | 'query' }>; + } + >; +} +export type VisState850 = XYVisState850; export type VisState840 = VisState830; export type LensDocShape840 = LensDocShape830; diff --git a/x-pack/plugins/lists/public/exceptions/api.test.ts b/x-pack/plugins/lists/public/exceptions/api.test.ts index a7d55139b7f5a4..c6f423184f9268 100644 --- a/x-pack/plugins/lists/public/exceptions/api.test.ts +++ b/x-pack/plugins/lists/public/exceptions/api.test.ts @@ -380,7 +380,6 @@ describe('Exceptions Lists API', () => { test('it invokes "fetchExceptionListsItemsByListIds" with expected url and body values', async () => { await fetchExceptionListsItemsByListIds({ - filterOptions: [], http: httpMock, listIds: ['myList', 'myOtherListId'], namespaceTypes: ['single', 'single'], @@ -405,14 +404,9 @@ describe('Exceptions Lists API', () => { }); }); - test('it invokes with expected url and body values when a filter exists and "namespaceType" of "single"', async () => { + test('it invokes with expected url and body values when a filter exists', async () => { await fetchExceptionListsItemsByListIds({ - filterOptions: [ - { - filter: 'hello world', - tags: [], - }, - ], + filter: 'exception-list.attributes.entries.field:hello world*', http: httpMock, listIds: ['myList'], namespaceTypes: ['single'], @@ -438,80 +432,8 @@ describe('Exceptions Lists API', () => { }); }); - test('it invokes with expected url and body values when a filter exists and "namespaceType" of "agnostic"', async () => { - await fetchExceptionListsItemsByListIds({ - filterOptions: [ - { - filter: 'hello world', - tags: [], - }, - ], - http: httpMock, - listIds: ['myList'], - namespaceTypes: ['agnostic'], - pagination: { - page: 1, - perPage: 20, - }, - signal: abortCtrl.signal, - }); - - expect(httpMock.fetch).toHaveBeenCalledWith('/api/exception_lists/items/_find', { - method: 'GET', - query: { - filter: 'exception-list-agnostic.attributes.entries.field:hello world*', - list_id: 'myList', - namespace_type: 'agnostic', - page: '1', - per_page: '20', - sort_field: 'exception-list.created_at', - sort_order: 'desc', - }, - signal: abortCtrl.signal, - }); - }); - - test('it invokes with expected url and body values when tags exists', async () => { + test('it invokes with expected url and body values when search exists', async () => { await fetchExceptionListsItemsByListIds({ - filterOptions: [ - { - filter: '', - tags: ['malware'], - }, - ], - http: httpMock, - listIds: ['myList'], - namespaceTypes: ['agnostic'], - pagination: { - page: 1, - perPage: 20, - }, - signal: abortCtrl.signal, - }); - - expect(httpMock.fetch).toHaveBeenCalledWith('/api/exception_lists/items/_find', { - method: 'GET', - query: { - filter: 'exception-list-agnostic.attributes.tags:malware', - list_id: 'myList', - namespace_type: 'agnostic', - page: '1', - per_page: '20', - sort_field: 'exception-list.created_at', - sort_order: 'desc', - }, - signal: abortCtrl.signal, - }); - }); - - test('it invokes with expected url and body values when filter and tags exists', async () => { - await fetchExceptionListsItemsByListIds({ - filterOptions: [ - { - filter: 'host.name', - tags: ['malware'], - }, - ], http: httpMock, listIds: ['myList'], namespaceTypes: ['agnostic'], @@ -519,18 +441,18 @@ describe('Exceptions Lists API', () => { page: 1, perPage: 20, }, + search: '-@timestamp', signal: abortCtrl.signal, }); expect(httpMock.fetch).toHaveBeenCalledWith('/api/exception_lists/items/_find', { method: 'GET', query: { - filter: - 'exception-list-agnostic.attributes.entries.field:host.name* AND exception-list-agnostic.attributes.tags:malware', list_id: 'myList', namespace_type: 'agnostic', page: '1', per_page: '20', + search: '-@timestamp', sort_field: 'exception-list.created_at', sort_order: 'desc', }, @@ -540,7 +462,6 @@ describe('Exceptions Lists API', () => { test('it returns expected format when call succeeds', async () => { const exceptionResponse = await fetchExceptionListsItemsByListIds({ - filterOptions: [], http: httpMock, listIds: ['endpoint_list_id'], namespaceTypes: ['single'], @@ -561,7 +482,6 @@ describe('Exceptions Lists API', () => { await expect( fetchExceptionListsItemsByListIds({ - filterOptions: [], http: httpMock, listIds: ['myList'], namespaceTypes: ['single'], diff --git a/x-pack/plugins/lists/public/exceptions/hooks/use_api.test.ts b/x-pack/plugins/lists/public/exceptions/hooks/use_api.test.ts index 0bd97dffb34f84..bf10fb57f1a5c3 100644 --- a/x-pack/plugins/lists/public/exceptions/hooks/use_api.test.ts +++ b/x-pack/plugins/lists/public/exceptions/hooks/use_api.test.ts @@ -297,7 +297,6 @@ describe('useApi', () => { await waitForNextUpdate(); await result.current.getExceptionListsItems({ - filterOptions: [], lists: [ { id: 'myListId', listId: 'list_id', namespaceType: 'single', type: 'detection' }, ], @@ -313,7 +312,6 @@ describe('useApi', () => { }); const expected: ApiCallByListIdProps = { - filterOptions: [], http: mockKibanaHttpService, listIds: ['list_id'], namespaceTypes: ['single'], @@ -351,7 +349,6 @@ describe('useApi', () => { await waitForNextUpdate(); await result.current.getExceptionListsItems({ - filterOptions: [], lists: [ { id: 'myListId', listId: 'list_id', namespaceType: 'single', type: 'detection' }, ], @@ -389,7 +386,6 @@ describe('useApi', () => { await waitForNextUpdate(); await result.current.getExceptionListsItems({ - filterOptions: [], lists: [ { id: 'myListId', listId: 'list_id', namespaceType: 'single', type: 'detection' }, ], diff --git a/x-pack/plugins/lists/public/exceptions/hooks/use_exception_list_items.test.ts b/x-pack/plugins/lists/public/exceptions/hooks/use_exception_list_items.test.ts deleted file mode 100644 index d8ae72d4d62054..00000000000000 --- a/x-pack/plugins/lists/public/exceptions/hooks/use_exception_list_items.test.ts +++ /dev/null @@ -1,498 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { act, renderHook } from '@testing-library/react-hooks'; -import type { - ExceptionListItemSchema, - UseExceptionListItemsSuccess, - UseExceptionListProps, -} from '@kbn/securitysolution-io-ts-list-types'; -import * as api from '@kbn/securitysolution-list-api'; -import { - ReturnExceptionListAndItems, - transformInput, - useExceptionListItems, -} from '@kbn/securitysolution-list-hooks'; -import { coreMock } from '@kbn/core/public/mocks'; - -import { getFoundExceptionListItemSchemaMock } from '../../../common/schemas/response/found_exception_list_item_schema.mock'; - -jest.mock('uuid', () => ({ - v4: jest.fn().mockReturnValue('123'), -})); -jest.mock('@kbn/securitysolution-list-api'); - -const mockKibanaHttpService = coreMock.createStart().http; - -// TODO: Port all of this test code over to the package of: packages/kbn-securitysolution-list-hooks/src/use_exception_list_items/index.test.ts once the mocks and kibana core mocks are figured out - -describe('useExceptionListItems', () => { - const onErrorMock = jest.fn(); - - beforeEach(() => { - jest - .spyOn(api, 'fetchExceptionListsItemsByListIds') - .mockResolvedValue(getFoundExceptionListItemSchemaMock()); - }); - - afterEach(() => { - onErrorMock.mockClear(); - jest.clearAllMocks(); - }); - - test('initializes hook', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook< - UseExceptionListProps, - ReturnExceptionListAndItems - >(() => - useExceptionListItems({ - filterOptions: [], - http: mockKibanaHttpService, - lists: [ - { id: 'myListId', listId: 'list_id', namespaceType: 'single', type: 'detection' }, - ], - matchFilters: false, - onError: onErrorMock, - pagination: { - page: 1, - perPage: 20, - total: 0, - }, - showDetectionsListsOnly: false, - showEndpointListsOnly: false, - }) - ); - await waitForNextUpdate(); - - expect(result.current).toEqual([ - true, - [], - { - page: 1, - perPage: 20, - total: 0, - }, - null, - ]); - }); - }); - - test('fetches exception items', async () => { - await act(async () => { - const onSuccessMock = jest.fn(); - const { result, waitForNextUpdate } = renderHook< - UseExceptionListProps, - ReturnExceptionListAndItems - >(() => - useExceptionListItems({ - filterOptions: [], - http: mockKibanaHttpService, - lists: [ - { id: 'myListId', listId: 'list_id', namespaceType: 'single', type: 'detection' }, - ], - matchFilters: false, - onError: onErrorMock, - onSuccess: onSuccessMock, - pagination: { - page: 1, - perPage: 20, - total: 0, - }, - showDetectionsListsOnly: false, - showEndpointListsOnly: false, - }) - ); - // NOTE: First `waitForNextUpdate` is initialization - // Second call applies the params - await waitForNextUpdate(); - await waitForNextUpdate(); - - const expectedListItemsResult: ExceptionListItemSchema[] = - getFoundExceptionListItemSchemaMock().data.map((item) => transformInput(item)); - const expectedResult: UseExceptionListItemsSuccess = { - exceptions: expectedListItemsResult, - pagination: { page: 1, perPage: 1, total: 1 }, - }; - - expect(result.current).toEqual([ - false, - expectedListItemsResult, - { - page: 1, - perPage: 1, - total: 1, - }, - result.current[3], - ]); - expect(onSuccessMock).toHaveBeenCalledWith(expectedResult); - }); - }); - - test('fetches only detection list items if "showDetectionsListsOnly" is true', async () => { - const spyOnfetchExceptionListsItemsByListIds = jest.spyOn( - api, - 'fetchExceptionListsItemsByListIds' - ); - - await act(async () => { - const onSuccessMock = jest.fn(); - const { waitForNextUpdate } = renderHook( - () => - useExceptionListItems({ - filterOptions: [], - http: mockKibanaHttpService, - lists: [ - { id: 'myListId', listId: 'list_id', namespaceType: 'single', type: 'detection' }, - { - id: 'myListIdEndpoint', - listId: 'list_id_endpoint', - namespaceType: 'agnostic', - type: 'endpoint', - }, - ], - matchFilters: false, - onError: onErrorMock, - onSuccess: onSuccessMock, - pagination: { - page: 1, - perPage: 20, - total: 0, - }, - showDetectionsListsOnly: true, - showEndpointListsOnly: false, - }) - ); - // NOTE: First `waitForNextUpdate` is initialization - // Second call applies the params - await waitForNextUpdate(); - await waitForNextUpdate(); - - expect(spyOnfetchExceptionListsItemsByListIds).toHaveBeenCalledWith({ - filterOptions: [], - http: mockKibanaHttpService, - listIds: ['list_id'], - namespaceTypes: ['single'], - pagination: { page: 1, perPage: 20 }, - signal: new AbortController().signal, - }); - }); - }); - - test('fetches only detection list items if "showEndpointListsOnly" is true', async () => { - const spyOnfetchExceptionListsItemsByListIds = jest.spyOn( - api, - 'fetchExceptionListsItemsByListIds' - ); - - await act(async () => { - const onSuccessMock = jest.fn(); - const { waitForNextUpdate } = renderHook( - () => - useExceptionListItems({ - filterOptions: [], - http: mockKibanaHttpService, - lists: [ - { id: 'myListId', listId: 'list_id', namespaceType: 'single', type: 'detection' }, - { - id: 'myListIdEndpoint', - listId: 'list_id_endpoint', - namespaceType: 'agnostic', - type: 'endpoint', - }, - ], - matchFilters: false, - onError: onErrorMock, - onSuccess: onSuccessMock, - pagination: { - page: 1, - perPage: 20, - total: 0, - }, - showDetectionsListsOnly: false, - showEndpointListsOnly: true, - }) - ); - // NOTE: First `waitForNextUpdate` is initialization - // Second call applies the params - await waitForNextUpdate(); - await waitForNextUpdate(); - - expect(spyOnfetchExceptionListsItemsByListIds).toHaveBeenCalledWith({ - filterOptions: [], - http: mockKibanaHttpService, - listIds: ['list_id_endpoint'], - namespaceTypes: ['agnostic'], - pagination: { page: 1, perPage: 20 }, - signal: new AbortController().signal, - }); - }); - }); - - test('does not fetch items if no lists to fetch', async () => { - const spyOnfetchExceptionListsItemsByListIds = jest.spyOn( - api, - 'fetchExceptionListsItemsByListIds' - ); - - await act(async () => { - const onSuccessMock = jest.fn(); - const { result, waitForNextUpdate } = renderHook< - UseExceptionListProps, - ReturnExceptionListAndItems - >(() => - useExceptionListItems({ - filterOptions: [], - http: mockKibanaHttpService, - lists: [ - { id: 'myListId', listId: 'list_id', namespaceType: 'single', type: 'detection' }, - ], - matchFilters: false, - onError: onErrorMock, - onSuccess: onSuccessMock, - pagination: { - page: 1, - perPage: 20, - total: 0, - }, - showDetectionsListsOnly: false, - showEndpointListsOnly: true, - }) - ); - // NOTE: First `waitForNextUpdate` is initialization - // Second call applies the params - await waitForNextUpdate(); - await waitForNextUpdate(); - - expect(spyOnfetchExceptionListsItemsByListIds).not.toHaveBeenCalled(); - expect(result.current).toEqual([ - false, - [], - { - page: 0, - perPage: 20, - total: 0, - }, - result.current[3], - ]); - }); - }); - - test('applies first filterOptions filter to all lists if "matchFilters" is true', async () => { - const spyOnfetchExceptionListsItemsByListIds = jest.spyOn( - api, - 'fetchExceptionListsItemsByListIds' - ); - - await act(async () => { - const onSuccessMock = jest.fn(); - const { waitForNextUpdate } = renderHook( - () => - useExceptionListItems({ - filterOptions: [{ filter: 'host.name', tags: [] }], - http: mockKibanaHttpService, - lists: [ - { id: 'myListId', listId: 'list_id', namespaceType: 'single', type: 'detection' }, - { - id: 'myListIdEndpoint', - listId: 'list_id_endpoint', - namespaceType: 'agnostic', - type: 'endpoint', - }, - ], - matchFilters: true, - onError: onErrorMock, - onSuccess: onSuccessMock, - pagination: { - page: 1, - perPage: 20, - total: 0, - }, - showDetectionsListsOnly: false, - showEndpointListsOnly: false, - }) - ); - // NOTE: First `waitForNextUpdate` is initialization - // Second call applies the params - await waitForNextUpdate(); - await waitForNextUpdate(); - - expect(spyOnfetchExceptionListsItemsByListIds).toHaveBeenCalledWith({ - filterOptions: [ - { filter: 'host.name', tags: [] }, - { filter: 'host.name', tags: [] }, - ], - http: mockKibanaHttpService, - listIds: ['list_id', 'list_id_endpoint'], - namespaceTypes: ['single', 'agnostic'], - pagination: { page: 1, perPage: 20 }, - signal: new AbortController().signal, - }); - }); - }); - - test('fetches a new exception list and its items', async () => { - const spyOnfetchExceptionListsItemsByListIds = jest.spyOn( - api, - 'fetchExceptionListsItemsByListIds' - ); - const onSuccessMock = jest.fn(); - await act(async () => { - const { rerender, waitForNextUpdate } = renderHook< - UseExceptionListProps, - ReturnExceptionListAndItems - >( - ({ - filterOptions, - http, - lists, - matchFilters, - pagination, - onError, - onSuccess, - showDetectionsListsOnly, - showEndpointListsOnly, - }) => - useExceptionListItems({ - filterOptions, - http, - lists, - matchFilters, - onError, - onSuccess, - pagination, - showDetectionsListsOnly, - showEndpointListsOnly, - }), - { - initialProps: { - filterOptions: [], - http: mockKibanaHttpService, - lists: [ - { id: 'myListId', listId: 'list_id', namespaceType: 'single', type: 'detection' }, - ], - matchFilters: false, - onError: onErrorMock, - onSuccess: onSuccessMock, - pagination: { - page: 1, - perPage: 20, - total: 0, - }, - showDetectionsListsOnly: false, - showEndpointListsOnly: false, - }, - } - ); - // NOTE: First `waitForNextUpdate` is initialization - // Second call applies the params - await waitForNextUpdate(); - await waitForNextUpdate(); - - rerender({ - filterOptions: [], - http: mockKibanaHttpService, - lists: [ - { id: 'newListId', listId: 'new_list_id', namespaceType: 'single', type: 'detection' }, - ], - matchFilters: false, - onError: onErrorMock, - onSuccess: onSuccessMock, - pagination: { - page: 1, - perPage: 20, - total: 0, - }, - showDetectionsListsOnly: false, - showEndpointListsOnly: false, - }); - // NOTE: Only need one call here because hook already initilaized - await waitForNextUpdate(); - - expect(spyOnfetchExceptionListsItemsByListIds).toHaveBeenCalledTimes(2); - }); - }); - - test('fetches list and items when refreshExceptionList callback invoked', async () => { - const spyOnfetchExceptionListsItemsByListIds = jest.spyOn( - api, - 'fetchExceptionListsItemsByListIds' - ); - await act(async () => { - const { result, waitForNextUpdate } = renderHook< - UseExceptionListProps, - ReturnExceptionListAndItems - >(() => - useExceptionListItems({ - filterOptions: [], - http: mockKibanaHttpService, - lists: [ - { id: 'myListId', listId: 'list_id', namespaceType: 'single', type: 'detection' }, - ], - matchFilters: false, - onError: onErrorMock, - pagination: { - page: 1, - perPage: 20, - total: 0, - }, - showDetectionsListsOnly: false, - showEndpointListsOnly: false, - }) - ); - // NOTE: First `waitForNextUpdate` is initialization - // Second call applies the params - await waitForNextUpdate(); - await waitForNextUpdate(); - - expect(typeof result.current[3]).toEqual('function'); - - if (result.current[3] != null) { - result.current[3](); - } - // NOTE: Only need one call here because hook already initilaized - await waitForNextUpdate(); - - expect(spyOnfetchExceptionListsItemsByListIds).toHaveBeenCalledTimes(2); - }); - }); - - test('invokes "onError" callback if "fetchExceptionListsItemsByListIds" fails', async () => { - const mockError = new Error('failed to fetches list items'); - const spyOnfetchExceptionListsItemsByListIds = jest - .spyOn(api, 'fetchExceptionListsItemsByListIds') - .mockRejectedValue(mockError); - await act(async () => { - const { waitForNextUpdate } = renderHook( - () => - useExceptionListItems({ - filterOptions: [], - http: mockKibanaHttpService, - lists: [ - { id: 'myListId', listId: 'list_id', namespaceType: 'single', type: 'detection' }, - ], - matchFilters: false, - onError: onErrorMock, - pagination: { - page: 1, - perPage: 20, - total: 0, - }, - showDetectionsListsOnly: false, - showEndpointListsOnly: false, - }) - ); - // NOTE: First `waitForNextUpdate` is initialization - // Second call applies the params - await waitForNextUpdate(); - await waitForNextUpdate(); - - expect(onErrorMock).toHaveBeenCalledWith(mockError); - expect(spyOnfetchExceptionListsItemsByListIds).toHaveBeenCalledTimes(1); - }); - }); -}); diff --git a/x-pack/plugins/lists/server/routes/find_exception_list_item_route.ts b/x-pack/plugins/lists/server/routes/find_exception_list_item_route.ts index b28ebf26b012cb..f77a3a7327d69f 100644 --- a/x-pack/plugins/lists/server/routes/find_exception_list_item_route.ts +++ b/x-pack/plugins/lists/server/routes/find_exception_list_item_route.ts @@ -42,6 +42,7 @@ export const findExceptionListItemRoute = (router: ListsPluginRouter): void => { namespace_type: namespaceType, page, per_page: perPage, + search, sort_field: sortField, sort_order: sortOrder, } = request.query; @@ -59,6 +60,7 @@ export const findExceptionListItemRoute = (router: ListsPluginRouter): void => { page, perPage, pit: undefined, + search, searchAfter: undefined, sortField, sortOrder, diff --git a/x-pack/plugins/lists/server/services/exception_lists/exception_list_client.ts b/x-pack/plugins/lists/server/services/exception_lists/exception_list_client.ts index c586a9d7641475..baa9d943127f76 100644 --- a/x-pack/plugins/lists/server/services/exception_lists/exception_list_client.ts +++ b/x-pack/plugins/lists/server/services/exception_lists/exception_list_client.ts @@ -717,6 +717,7 @@ export class ExceptionListClient { perPage, pit, page, + search, searchAfter, sortField, sortOrder, @@ -750,6 +751,7 @@ export class ExceptionListClient { perPage, pit, savedObjectsClient, + search, searchAfter, sortField, sortOrder, @@ -764,6 +766,7 @@ export class ExceptionListClient { * @param options.perPage How many per page to return * @param options.pit The Point in Time (pit) id if there is one, otherwise "undefined" can be sent in * @param options.page The page number or "undefined" if there is no page number to continue from + * @param options.search The simple query search parameter if there is one, otherwise "undefined" can be sent in * @param options.searchAfter The search_after parameter if there is one, otherwise "undefined" can be sent in * @param options.sortField The sort field string if there is one, otherwise "undefined" can be sent in * @param options.sortOder The sort order string of "asc", "desc", otherwise "undefined" if there is no preference @@ -776,6 +779,7 @@ export class ExceptionListClient { perPage, pit, page, + search, searchAfter, sortField, sortOrder, @@ -793,6 +797,7 @@ export class ExceptionListClient { page, perPage, pit, + search, searchAfter, sortField, sortOrder, @@ -809,6 +814,7 @@ export class ExceptionListClient { perPage, pit, savedObjectsClient, + search, searchAfter, sortField, sortOrder, @@ -898,6 +904,7 @@ export class ExceptionListClient { * @param options.perPage How many per page to return * @param options.page The page number or "undefined" if there is no page number to continue from * @param options.pit The Point in Time (pit) id if there is one, otherwise "undefined" can be sent in + * @param options.search The simple query search parameter if there is one, otherwise "undefined" can be sent in * @param options.searchAfter The search_after parameter if there is one, otherwise "undefined" can be sent in * @param options.sortField The sort field string if there is one, otherwise "undefined" can be sent in * @param options.sortOrder The sort order of "asc" or "desc", otherwise "undefined" can be sent in @@ -908,6 +915,7 @@ export class ExceptionListClient { perPage, page, pit, + search, searchAfter, sortField, sortOrder, @@ -922,6 +930,7 @@ export class ExceptionListClient { perPage, pit, savedObjectsClient, + search, searchAfter, sortField, sortOrder, diff --git a/x-pack/plugins/lists/server/services/exception_lists/exception_list_client_types.ts b/x-pack/plugins/lists/server/services/exception_lists/exception_list_client_types.ts index 2b3a800ac5a5a3..048930e51b93d7 100644 --- a/x-pack/plugins/lists/server/services/exception_lists/exception_list_client_types.ts +++ b/x-pack/plugins/lists/server/services/exception_lists/exception_list_client_types.ts @@ -46,6 +46,7 @@ import type { PitId, PitOrUndefined, SearchAfterOrUndefined, + SearchOrUndefined, SortFieldOrUndefined, SortOrderOrUndefined, Tags, @@ -361,6 +362,8 @@ export interface FindExceptionListItemOptions { perPage: PerPageOrUndefined; /** The Point in Time (pit) id if there is one, otherwise "undefined" can be send in */ pit?: PitOrUndefined; + /** The simple search parameter if there is one, otherwise "undefined" can be sent in */ + search?: SearchOrUndefined; /** The search_after parameter if there is one, otherwise "undefined" can be sent in */ searchAfter?: SearchAfterOrUndefined; /** The page number or "undefined" if there is no page number to continue from */ @@ -382,6 +385,8 @@ export interface FindEndpointListItemOptions { perPage: PerPageOrUndefined; /** The Point in Time (pit) id if there is one, otherwise "undefined" can be sent in */ pit?: PitOrUndefined; + /** The simple search parameter if there is one, otherwise "undefined" can be sent in */ + search?: SearchOrUndefined; /** The search_after parameter if there is one, otherwise "undefined" can be sent in */ searchAfter?: SearchAfterOrUndefined; /** The page number or "undefined" if there is no page number to continue from */ @@ -407,6 +412,8 @@ export interface FindExceptionListsItemOptions { perPage: PerPageOrUndefined; /** The Point in Time (pit) id if there is one, otherwise "undefined" can be sent in */ pit?: PitOrUndefined; + /** The simple search parameter if there is one, otherwise "undefined" can be sent in */ + search?: SearchOrUndefined; /** The search_after parameter if there is one, otherwise "undefined" can be sent in */ searchAfter?: SearchAfterOrUndefined; /** The page number or "undefined" if there is no page number to continue from */ diff --git a/x-pack/plugins/lists/server/services/exception_lists/find_exception_list_item.ts b/x-pack/plugins/lists/server/services/exception_lists/find_exception_list_item.ts index c08057d77ebbe4..fc41afd7563c71 100644 --- a/x-pack/plugins/lists/server/services/exception_lists/find_exception_list_item.ts +++ b/x-pack/plugins/lists/server/services/exception_lists/find_exception_list_item.ts @@ -15,6 +15,7 @@ import type { PerPageOrUndefined, PitOrUndefined, SearchAfterOrUndefined, + SearchOrUndefined, SortFieldOrUndefined, SortOrderOrUndefined, } from '@kbn/securitysolution-io-ts-list-types'; @@ -29,6 +30,7 @@ interface FindExceptionListItemOptions { page: PageOrUndefined; perPage: PerPageOrUndefined; pit: PitOrUndefined; + search: SearchOrUndefined; sortField: SortFieldOrUndefined; sortOrder: SortOrderOrUndefined; searchAfter: SearchAfterOrUndefined; @@ -42,6 +44,7 @@ export const findExceptionListItem = async ({ page, perPage, pit, + search, searchAfter, sortField, sortOrder, @@ -54,6 +57,7 @@ export const findExceptionListItem = async ({ perPage, pit, savedObjectsClient, + search, searchAfter, sortField, sortOrder, diff --git a/x-pack/plugins/lists/server/services/exception_lists/find_exception_list_items.ts b/x-pack/plugins/lists/server/services/exception_lists/find_exception_list_items.ts index f0e1fa07749f8d..f3fd291ecd0674 100644 --- a/x-pack/plugins/lists/server/services/exception_lists/find_exception_list_items.ts +++ b/x-pack/plugins/lists/server/services/exception_lists/find_exception_list_items.ts @@ -13,6 +13,7 @@ import type { PerPageOrUndefined, PitOrUndefined, SearchAfterOrUndefined, + SearchOrUndefined, SortFieldOrUndefined, SortOrderOrUndefined, } from '@kbn/securitysolution-io-ts-list-types'; @@ -39,6 +40,7 @@ interface FindExceptionListItemsOptions { sortField: SortFieldOrUndefined; sortOrder: SortOrderOrUndefined; searchAfter: SearchAfterOrUndefined; + search: SearchOrUndefined; } export const findExceptionListsItem = async ({ @@ -49,6 +51,7 @@ export const findExceptionListsItem = async ({ page, pit, perPage, + search, searchAfter, sortField, sortOrder, @@ -74,6 +77,7 @@ export const findExceptionListsItem = async ({ page, perPage, pit, + search, searchAfter, sortField, sortOrder, diff --git a/x-pack/plugins/ml/public/application/aiops/explain_log_rate_spikes.tsx b/x-pack/plugins/ml/public/application/aiops/explain_log_rate_spikes.tsx index 5d9a7fd3a84163..2a8ce6e04144cd 100644 --- a/x-pack/plugins/ml/public/application/aiops/explain_log_rate_spikes.tsx +++ b/x-pack/plugins/ml/public/application/aiops/explain_log_rate_spikes.tsx @@ -6,6 +6,7 @@ */ import React, { FC } from 'react'; +import { pick } from 'lodash'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; @@ -20,9 +21,7 @@ import { TechnicalPreviewBadge } from '../components/technical_preview_badge'; import { MlPageHeader } from '../components/page_header'; export const ExplainLogRateSpikesPage: FC = () => { - const { - services: { docLinks }, - } = useMlKibana(); + const { services } = useMlKibana(); const context = useMlContext(); const dataView = context.currentDataView; @@ -43,8 +42,25 @@ export const ExplainLogRateSpikesPage: FC = () => { - {dataView && } - + {dataView && ( + + )} + ); }; diff --git a/x-pack/plugins/ml/public/application/app.tsx b/x-pack/plugins/ml/public/application/app.tsx index 8e9a7d67d10ac8..fbfea9ef9a05bc 100644 --- a/x-pack/plugins/ml/public/application/app.tsx +++ b/x-pack/plugins/ml/public/application/app.tsx @@ -85,12 +85,12 @@ const App: FC = ({ coreStart, deps, appMountParams }) => { maps: deps.maps, triggersActionsUi: deps.triggersActionsUi, dataVisualizer: deps.dataVisualizer, - aiops: deps.aiops, usageCollection: deps.usageCollection, fieldFormats: deps.fieldFormats, dashboard: deps.dashboard, charts: deps.charts, cases: deps.cases, + unifiedSearch: deps.unifiedSearch, ...coreStart, }; @@ -140,7 +140,6 @@ export const renderApp = ( dashboard: deps.dashboard, maps: deps.maps, dataVisualizer: deps.dataVisualizer, - aiops: deps.aiops, dataViews: deps.data.dataViews, }); diff --git a/x-pack/plugins/ml/public/application/contexts/kibana/kibana_context.ts b/x-pack/plugins/ml/public/application/contexts/kibana/kibana_context.ts index e8e694b1b6f210..941352c8f8520a 100644 --- a/x-pack/plugins/ml/public/application/contexts/kibana/kibana_context.ts +++ b/x-pack/plugins/ml/public/application/contexts/kibana/kibana_context.ts @@ -16,13 +16,13 @@ import type { IStorageWrapper } from '@kbn/kibana-utils-plugin/public'; import type { EmbeddableStart } from '@kbn/embeddable-plugin/public'; import type { MapsStartApi } from '@kbn/maps-plugin/public'; import type { DataVisualizerPluginStart } from '@kbn/data-visualizer-plugin/public'; -import type { AiopsPluginStart } from '@kbn/aiops-plugin/public'; import type { TriggersAndActionsUIPublicPluginStart } from '@kbn/triggers-actions-ui-plugin/public'; import type { FieldFormatsRegistry } from '@kbn/field-formats-plugin/common'; import type { DashboardSetup } from '@kbn/dashboard-plugin/public'; import type { SpacesPluginStart } from '@kbn/spaces-plugin/public'; import type { ChartsPluginStart } from '@kbn/charts-plugin/public'; import type { CasesUiStart } from '@kbn/cases-plugin/public'; +import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public'; import type { MlServicesContext } from '../../app'; interface StartPlugins { @@ -34,13 +34,13 @@ interface StartPlugins { maps?: MapsStartApi; triggersActionsUi?: TriggersAndActionsUIPublicPluginStart; dataVisualizer?: DataVisualizerPluginStart; - aiops?: AiopsPluginStart; usageCollection?: UsageCollectionSetup; fieldFormats: FieldFormatsRegistry; dashboard: DashboardSetup; spacesApi: SpacesPluginStart; charts: ChartsPluginStart; cases?: CasesUiStart; + unifiedSearch: UnifiedSearchPublicPluginStart; } export type StartServices = CoreStart & StartPlugins & { diff --git a/x-pack/plugins/ml/public/application/util/dependency_cache.ts b/x-pack/plugins/ml/public/application/util/dependency_cache.ts index 00895cdb3990e8..3680f8b63b0c96 100644 --- a/x-pack/plugins/ml/public/application/util/dependency_cache.ts +++ b/x-pack/plugins/ml/public/application/util/dependency_cache.ts @@ -27,7 +27,6 @@ import type { DataViewsContract } from '@kbn/data-views-plugin/public'; import type { SecurityPluginSetup } from '@kbn/security-plugin/public'; import type { MapsStartApi } from '@kbn/maps-plugin/public'; import type { DataVisualizerPluginStart } from '@kbn/data-visualizer-plugin/public'; -import type { AiopsPluginStart } from '@kbn/aiops-plugin/public'; export interface DependencyCache { timefilter: DataPublicPluginSetup['query']['timefilter'] | null; @@ -49,7 +48,6 @@ export interface DependencyCache { dashboard: DashboardStart | null; maps: MapsStartApi | null; dataVisualizer: DataVisualizerPluginStart | null; - aiops: AiopsPluginStart | null; dataViews: DataViewsContract | null; } @@ -73,7 +71,6 @@ const cache: DependencyCache = { dashboard: null, maps: null, dataVisualizer: null, - aiops: null, dataViews: null, }; @@ -96,7 +93,6 @@ export function setDependencyCache(deps: Partial) { cache.i18n = deps.i18n || null; cache.dashboard = deps.dashboard || null; cache.dataVisualizer = deps.dataVisualizer || null; - cache.aiops = deps.aiops || null; cache.dataViews = deps.dataViews || null; } diff --git a/x-pack/plugins/ml/public/plugin.ts b/x-pack/plugins/ml/public/plugin.ts index 75d4a8d0fe54ba..9d084708e6529b 100644 --- a/x-pack/plugins/ml/public/plugin.ts +++ b/x-pack/plugins/ml/public/plugin.ts @@ -38,7 +38,6 @@ import { TriggersAndActionsUIPublicPluginStart, } from '@kbn/triggers-actions-ui-plugin/public'; import type { DataVisualizerPluginStart } from '@kbn/data-visualizer-plugin/public'; -import type { AiopsPluginStart } from '@kbn/aiops-plugin/public'; import type { PluginSetupContract as AlertingSetup } from '@kbn/alerting-plugin/public'; import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public'; import type { FieldFormatsSetup, FieldFormatsStart } from '@kbn/field-formats-plugin/public'; @@ -62,7 +61,6 @@ export interface MlStartDependencies { maps?: MapsStartApi; triggersActionsUi?: TriggersAndActionsUIPublicPluginStart; dataVisualizer: DataVisualizerPluginStart; - aiops: AiopsPluginStart; fieldFormats: FieldFormatsStart; dashboard: DashboardStart; charts: ChartsPluginStart; @@ -132,7 +130,6 @@ export class MlPlugin implements Plugin { kibanaVersion, triggersActionsUi: pluginsStart.triggersActionsUi, dataVisualizer: pluginsStart.dataVisualizer, - aiops: pluginsStart.aiops, usageCollection: pluginsSetup.usageCollection, fieldFormats: pluginsStart.fieldFormats, lens: pluginsStart.lens, diff --git a/x-pack/plugins/observability/public/pages/rule_details/index.tsx b/x-pack/plugins/observability/public/pages/rule_details/index.tsx index 88602fd3ed255b..27bbc1fc0f4a0a 100644 --- a/x-pack/plugins/observability/public/pages/rule_details/index.tsx +++ b/x-pack/plugins/observability/public/pages/rule_details/index.tsx @@ -185,7 +185,7 @@ export function RuleDetailsPage() { }), 'data-test-subj': 'eventLogListTab', content: getRuleEventLogList<'default'>({ - rule, + ruleId: rule?.id, ruleType, } as RuleEventLogListProps), }, diff --git a/x-pack/plugins/security_solution/common/constants.ts b/x-pack/plugins/security_solution/common/constants.ts index e86e57e00ca346..6f3958cbb54e1b 100644 --- a/x-pack/plugins/security_solution/common/constants.ts +++ b/x-pack/plugins/security_solution/common/constants.ts @@ -290,10 +290,13 @@ export const prebuiltSavedObjectsBulkCreateUrl = (templateName: string) => * Internal detection engine routes */ export const INTERNAL_DETECTION_ENGINE_URL = '/internal/detection_engine' as const; +export const INTERNAL_DETECTION_ENGINE_RULES_URL = '/internal/detection_engine/rules' as const; export const DETECTION_ENGINE_INSTALLED_INTEGRATIONS_URL = `${INTERNAL_DETECTION_ENGINE_URL}/fleet/integrations/installed` as const; export const DETECTION_ENGINE_ALERTS_INDEX_URL = `${INTERNAL_DETECTION_ENGINE_URL}/signal/index` as const; +export const DETECTION_ENGINE_RULES_EXCEPTIONS_REFERENCE_URL = + `${INTERNAL_DETECTION_ENGINE_RULES_URL}/exceptions/_find_references` as const; /** * Telemetry detection endpoint for any previews requested of what data we are * providing through UI/UX and for e2e tests. diff --git a/x-pack/plugins/security_solution/common/detection_engine/schemas/request/find_exception_list_references_schema.test.ts b/x-pack/plugins/security_solution/common/detection_engine/schemas/request/find_exception_list_references_schema.test.ts new file mode 100644 index 00000000000000..425928d8fa2085 --- /dev/null +++ b/x-pack/plugins/security_solution/common/detection_engine/schemas/request/find_exception_list_references_schema.test.ts @@ -0,0 +1,90 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { exactCheck, formatErrors, foldLeftRight } from '@kbn/securitysolution-io-ts-utils'; +import { findExceptionReferencesOnRuleSchema } from './find_exception_list_references_schema'; +import type { FindExceptionReferencesOnRuleSchema } from './find_exception_list_references_schema'; + +describe('find_exception_list_references_schema', () => { + test('validates all fields', () => { + const payload: FindExceptionReferencesOnRuleSchema = { + ids: 'abc,def', + list_ids: '123,456', + namespace_types: 'single,agnostic', + }; + + const decoded = findExceptionReferencesOnRuleSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const output = foldLeftRight(checked); + expect(formatErrors(output.errors)).toEqual([]); + expect(output.schema).toEqual({ + ids: ['abc', 'def'], + list_ids: ['123', '456'], + namespace_types: ['single', 'agnostic'], + }); + }); + + test('"ids" cannot be undefined', () => { + const payload: Omit = { + list_ids: '123,456', + namespace_types: 'single,agnostic', + }; + + const decoded = findExceptionReferencesOnRuleSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const output = foldLeftRight(checked); + expect(formatErrors(output.errors)).toEqual(['Invalid value "undefined" supplied to "ids"']); + expect(output.schema).toEqual({}); + }); + + test('"list_ids" cannot be undefined', () => { + const payload: Omit = { + ids: 'abc', + namespace_types: 'single', + }; + + const decoded = findExceptionReferencesOnRuleSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const output = foldLeftRight(checked); + expect(formatErrors(output.errors)).toEqual([ + 'Invalid value "undefined" supplied to "list_ids"', + ]); + expect(output.schema).toEqual({}); + }); + + test('defaults "namespacetypes" to ["single"] if none set', () => { + const payload: Omit = { + ids: 'abc', + list_ids: '123', + }; + + const decoded = findExceptionReferencesOnRuleSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const output = foldLeftRight(checked); + expect(formatErrors(output.errors)).toEqual([]); + expect(output.schema).toEqual({ + ids: ['abc'], + list_ids: ['123'], + namespace_types: ['single'], + }); + }); + + test('cannot add extra values', () => { + const payload: FindExceptionReferencesOnRuleSchema & { extra_value?: string } = { + ids: 'abc,def', + list_ids: '123,456', + namespace_types: 'single,agnostic', + extra_value: 'aaa', + }; + + const decoded = findExceptionReferencesOnRuleSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const output = foldLeftRight(checked); + expect(formatErrors(output.errors)).toEqual(['invalid keys "extra_value"']); + expect(output.schema).toEqual({}); + }); +}); diff --git a/x-pack/plugins/security_solution/common/detection_engine/schemas/request/find_exception_list_references_schema.ts b/x-pack/plugins/security_solution/common/detection_engine/schemas/request/find_exception_list_references_schema.ts new file mode 100644 index 00000000000000..8cd21df8ab08ba --- /dev/null +++ b/x-pack/plugins/security_solution/common/detection_engine/schemas/request/find_exception_list_references_schema.ts @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import * as t from 'io-ts'; +import { NonEmptyStringArray } from '@kbn/securitysolution-io-ts-types'; +import { DefaultNamespaceArray } from '@kbn/securitysolution-io-ts-list-types'; + +export const findExceptionReferencesOnRuleSchema = t.exact( + t.type({ + ids: NonEmptyStringArray, + list_ids: NonEmptyStringArray, + namespace_types: DefaultNamespaceArray, + }) +); + +export type FindExceptionReferencesOnRuleSchema = t.OutputOf< + typeof findExceptionReferencesOnRuleSchema +>; + +export type FindExceptionReferencesOnRuleSchemaDecoded = t.TypeOf< + typeof findExceptionReferencesOnRuleSchema +>; diff --git a/x-pack/plugins/security_solution/common/detection_engine/schemas/response/find_exception_list_references_schema.test.ts b/x-pack/plugins/security_solution/common/detection_engine/schemas/response/find_exception_list_references_schema.test.ts new file mode 100644 index 00000000000000..743645ba0f818c --- /dev/null +++ b/x-pack/plugins/security_solution/common/detection_engine/schemas/response/find_exception_list_references_schema.test.ts @@ -0,0 +1,169 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { exactCheck, formatErrors, foldLeftRight } from '@kbn/securitysolution-io-ts-utils'; +import { + ruleReferenceSchema, + rulesReferencedByExceptionListsSchema, +} from './find_exception_list_references_schema'; +import type { + RuleReferenceSchema, + RulesReferencedByExceptionListsSchema, +} from './find_exception_list_references_schema'; + +describe('find_exception_list_references_schema', () => { + describe('ruleReferenceSchema', () => { + test('validates all fields', () => { + const payload: RuleReferenceSchema = { + name: 'My rule', + id: '4656dc92-5832-11ea-8e2d-0242ac130003', + rule_id: 'my-rule-id', + exception_lists: [ + { + id: 'myListId', + list_id: 'my-list-id', + namespace_type: 'single', + type: 'detection', + }, + ], + }; + + const decoded = ruleReferenceSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const output = foldLeftRight(checked); + expect(formatErrors(output.errors)).toEqual([]); + expect(output.schema).toEqual({ + exception_lists: [ + { id: 'myListId', list_id: 'my-list-id', namespace_type: 'single', type: 'detection' }, + ], + id: '4656dc92-5832-11ea-8e2d-0242ac130003', + name: 'My rule', + rule_id: 'my-rule-id', + }); + }); + + test('cannot add extra values', () => { + const payload: RuleReferenceSchema & { extra_value?: string } = { + name: 'My rule', + id: '4656dc92-5832-11ea-8e2d-0242ac130003', + rule_id: 'my-rule-id', + extra_value: 'foo', + exception_lists: [ + { + id: 'myListId', + list_id: 'my-list-id', + namespace_type: 'single', + type: 'detection', + }, + ], + }; + + const decoded = ruleReferenceSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const output = foldLeftRight(checked); + expect(formatErrors(output.errors)).toEqual(['invalid keys "extra_value"']); + expect(output.schema).toEqual({}); + }); + }); + + describe('rulesReferencedByExceptionListsSchema', () => { + test('validates all fields', () => { + const payload: RulesReferencedByExceptionListsSchema = { + references: [ + { + 'my-list-id': [ + { + name: 'My rule', + id: '4656dc92-5832-11ea-8e2d-0242ac130003', + rule_id: 'my-rule-id', + exception_lists: [ + { + id: 'myListId', + list_id: 'my-list-id', + namespace_type: 'single', + type: 'detection', + }, + ], + }, + ], + }, + ], + }; + + const decoded = rulesReferencedByExceptionListsSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const output = foldLeftRight(checked); + expect(formatErrors(output.errors)).toEqual([]); + expect(output.schema).toEqual({ + references: [ + { + 'my-list-id': [ + { + exception_lists: [ + { + id: 'myListId', + list_id: 'my-list-id', + namespace_type: 'single', + type: 'detection', + }, + ], + id: '4656dc92-5832-11ea-8e2d-0242ac130003', + name: 'My rule', + rule_id: 'my-rule-id', + }, + ], + }, + ], + }); + }); + + test('validates "references" with empty array', () => { + const payload: RulesReferencedByExceptionListsSchema = { + references: [], + }; + + const decoded = rulesReferencedByExceptionListsSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const output = foldLeftRight(checked); + expect(formatErrors(output.errors)).toEqual([]); + expect(output.schema).toEqual({ + references: [], + }); + }); + + test('cannot add extra values', () => { + const payload: RulesReferencedByExceptionListsSchema & { extra_value?: string } = { + extra_value: 'foo', + references: [ + { + 'my-list-id': [ + { + name: 'My rule', + id: '4656dc92-5832-11ea-8e2d-0242ac130003', + rule_id: 'my-rule-id', + exception_lists: [ + { + id: 'myListId', + list_id: 'my-list-id', + namespace_type: 'single', + type: 'detection', + }, + ], + }, + ], + }, + ], + }; + + const decoded = rulesReferencedByExceptionListsSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const output = foldLeftRight(checked); + expect(formatErrors(output.errors)).toEqual(['invalid keys "extra_value"']); + expect(output.schema).toEqual({}); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/common/detection_engine/schemas/response/find_exception_list_references_schema.ts b/x-pack/plugins/security_solution/common/detection_engine/schemas/response/find_exception_list_references_schema.ts new file mode 100644 index 00000000000000..a7f2527edc0965 --- /dev/null +++ b/x-pack/plugins/security_solution/common/detection_engine/schemas/response/find_exception_list_references_schema.ts @@ -0,0 +1,37 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import * as t from 'io-ts'; + +import { listArray, list_id } from '@kbn/securitysolution-io-ts-list-types'; + +import { rule_id, id, name } from '../common/schemas'; + +export const ruleReferenceSchema = t.exact( + t.type({ + name, + id, + rule_id, + exception_lists: listArray, + }) +); + +export type RuleReferenceSchema = t.OutputOf; + +export const rulesReferencedByExceptionListSchema = t.record(list_id, t.array(ruleReferenceSchema)); + +export type RuleReferencesSchema = t.OutputOf; + +export const rulesReferencedByExceptionListsSchema = t.exact( + t.type({ + references: t.array(rulesReferencedByExceptionListSchema), + }) +); + +export type RulesReferencedByExceptionListsSchema = t.OutputOf< + typeof rulesReferencedByExceptionListsSchema +>; diff --git a/x-pack/plugins/security_solution/common/detection_engine/schemas/response/index.ts b/x-pack/plugins/security_solution/common/detection_engine/schemas/response/index.ts index 1b688ce641a7a9..e12fbf29183029 100644 --- a/x-pack/plugins/security_solution/common/detection_engine/schemas/response/index.ts +++ b/x-pack/plugins/security_solution/common/detection_engine/schemas/response/index.ts @@ -7,6 +7,7 @@ export * from './error_schema'; export * from './get_installed_integrations_response_schema'; +export * from './find_exception_list_references_schema'; export * from './import_rules_schema'; export * from './prepackaged_rules_schema'; export * from './prepackaged_rules_status_schema'; diff --git a/x-pack/plugins/security_solution/cypress/integration/exceptions/add_edit_data_view_exception.spec.ts b/x-pack/plugins/security_solution/cypress/integration/exceptions/add_edit_data_view_exception.spec.ts deleted file mode 100644 index c818f4e51060ff..00000000000000 --- a/x-pack/plugins/security_solution/cypress/integration/exceptions/add_edit_data_view_exception.spec.ts +++ /dev/null @@ -1,159 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { getException } from '../../objects/exception'; -import { getNewRule } from '../../objects/rule'; - -import { ALERTS_COUNT, EMPTY_ALERT_TABLE, NUMBER_OF_ALERTS } from '../../screens/alerts'; - -import { addExceptionFromFirstAlert, goToClosedAlerts, goToOpenedAlerts } from '../../tasks/alerts'; -import { createCustomRuleEnabled } from '../../tasks/api_calls/rules'; -import { goToRuleDetails } from '../../tasks/alerts_detection_rules'; -import { waitForAlertsToPopulate } from '../../tasks/create_new_rule'; -import { esArchiverLoad, esArchiverUnload, esArchiverResetKibana } from '../../tasks/es_archiver'; -import { login, visitWithoutDateRange } from '../../tasks/login'; -import { - addsException, - addsExceptionFromRuleSettings, - editException, - goToAlertsTab, - goToExceptionsTab, - removeException, - waitForTheRuleToBeExecuted, -} from '../../tasks/rule_details'; - -import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../urls/navigation'; -import { deleteAlertsAndRules, postDataView } from '../../tasks/common'; -import { - EXCEPTION_EDIT_FLYOUT_SAVE_BTN, - EXCEPTION_ITEM_CONTAINER, - FIELD_INPUT, -} from '../../screens/exceptions'; -import { - addExceptionEntryFieldValueOfItemX, - addExceptionEntryFieldValueValue, -} from '../../tasks/exceptions'; - -describe('Adds rule exception using data views', () => { - const NUMBER_OF_AUDITBEAT_EXCEPTIONS_ALERTS = '1 alert'; - - before(() => { - esArchiverResetKibana(); - esArchiverLoad('exceptions'); - login(); - - postDataView('exceptions-*'); - }); - - beforeEach(() => { - deleteAlertsAndRules(); - createCustomRuleEnabled( - { - ...getNewRule(), - customQuery: 'agent.name:*', - dataSource: { dataView: 'exceptions-*', type: 'dataView' }, - }, - 'rule_testing', - '1s' - ); - visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL); - goToRuleDetails(); - waitForTheRuleToBeExecuted(); - waitForAlertsToPopulate(); - }); - - afterEach(() => { - esArchiverUnload('exceptions_2'); - }); - - after(() => { - esArchiverUnload('exceptions'); - }); - - it('Creates an exception from an alert and deletes it', () => { - cy.get(ALERTS_COUNT).should('exist'); - cy.get(NUMBER_OF_ALERTS).should('have.text', NUMBER_OF_AUDITBEAT_EXCEPTIONS_ALERTS); - // Create an exception from the alerts actions menu that matches - // the existing alert - addExceptionFromFirstAlert(); - addsException(getException()); - - // Alerts table should now be empty from having added exception and closed - // matching alert - cy.get(EMPTY_ALERT_TABLE).should('exist'); - - // Closed alert should appear in table - goToClosedAlerts(); - cy.get(ALERTS_COUNT).should('exist'); - cy.get(NUMBER_OF_ALERTS).should('have.text', `${NUMBER_OF_AUDITBEAT_EXCEPTIONS_ALERTS}`); - - // Remove the exception and load an event that would have matched that exception - // to show that said exception now starts to show up again - goToExceptionsTab(); - removeException(); - esArchiverLoad('exceptions_2'); - goToAlertsTab(); - goToOpenedAlerts(); - waitForTheRuleToBeExecuted(); - waitForAlertsToPopulate(); - - cy.get(ALERTS_COUNT).should('exist'); - cy.get(NUMBER_OF_ALERTS).should('have.text', `${NUMBER_OF_AUDITBEAT_EXCEPTIONS_ALERTS}`); - }); - - it('Creates an exception from a rule and deletes it', () => { - // Create an exception from the exception tab that matches - // the existing alert - goToExceptionsTab(); - addsExceptionFromRuleSettings(getException()); - - // Alerts table should now be empty from having added exception and closed - // matching alert - goToAlertsTab(); - cy.get(EMPTY_ALERT_TABLE).should('exist'); - - // Closed alert should appear in table - goToClosedAlerts(); - cy.get(ALERTS_COUNT).should('exist'); - cy.get(NUMBER_OF_ALERTS).should('have.text', `${NUMBER_OF_AUDITBEAT_EXCEPTIONS_ALERTS}`); - - // Remove the exception and load an event that would have matched that exception - // to show that said exception now starts to show up again - goToExceptionsTab(); - removeException(); - esArchiverLoad('exceptions_2'); - goToAlertsTab(); - goToOpenedAlerts(); - waitForTheRuleToBeExecuted(); - waitForAlertsToPopulate(); - - cy.get(ALERTS_COUNT).should('exist'); - cy.get(NUMBER_OF_ALERTS).should('have.text', `${NUMBER_OF_AUDITBEAT_EXCEPTIONS_ALERTS}`); - }); - - it('Edits an exception', () => { - goToExceptionsTab(); - addsExceptionFromRuleSettings(getException()); - - editException(); - - // check that the existing item's field is being populated - cy.get(EXCEPTION_ITEM_CONTAINER) - .eq(0) - .find(FIELD_INPUT) - .eq(0) - .should('have.text', 'agent.name'); - - // check that you can select a different field - addExceptionEntryFieldValueOfItemX('user.name{downarrow}{enter}', 0, 0); - addExceptionEntryFieldValueValue('test', 0); - - cy.get(EXCEPTION_EDIT_FLYOUT_SAVE_BTN).click(); - cy.get(EXCEPTION_EDIT_FLYOUT_SAVE_BTN).should('have.attr', 'disabled'); - cy.get(EXCEPTION_EDIT_FLYOUT_SAVE_BTN).should('not.exist'); - }); -}); diff --git a/x-pack/plugins/security_solution/cypress/integration/exceptions/add_edit_exception.spec.ts b/x-pack/plugins/security_solution/cypress/integration/exceptions/add_edit_exception.spec.ts deleted file mode 100644 index 886f772bc25e5e..00000000000000 --- a/x-pack/plugins/security_solution/cypress/integration/exceptions/add_edit_exception.spec.ts +++ /dev/null @@ -1,157 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { getException } from '../../objects/exception'; -import { getNewRule } from '../../objects/rule'; - -import { ALERTS_COUNT, EMPTY_ALERT_TABLE, NUMBER_OF_ALERTS } from '../../screens/alerts'; - -import { addExceptionFromFirstAlert, goToClosedAlerts, goToOpenedAlerts } from '../../tasks/alerts'; -import { createCustomRuleEnabled } from '../../tasks/api_calls/rules'; -import { goToRuleDetails } from '../../tasks/alerts_detection_rules'; -import { waitForAlertsToPopulate } from '../../tasks/create_new_rule'; -import { esArchiverLoad, esArchiverUnload, esArchiverResetKibana } from '../../tasks/es_archiver'; -import { login, visitWithoutDateRange } from '../../tasks/login'; -import { - addsException, - addsExceptionFromRuleSettings, - editException, - goToAlertsTab, - goToExceptionsTab, - removeException, - waitForTheRuleToBeExecuted, -} from '../../tasks/rule_details'; - -import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../urls/navigation'; -import { deleteAlertsAndRules } from '../../tasks/common'; -import { - EXCEPTION_EDIT_FLYOUT_SAVE_BTN, - EXCEPTION_ITEM_CONTAINER, - FIELD_INPUT, -} from '../../screens/exceptions'; -import { - addExceptionEntryFieldValueOfItemX, - addExceptionEntryFieldValueValue, -} from '../../tasks/exceptions'; - -describe('Adds rule exception', () => { - const NUMBER_OF_AUDITBEAT_EXCEPTIONS_ALERTS = '1 alert'; - - before(() => { - esArchiverResetKibana(); - esArchiverLoad('exceptions'); - login(); - }); - - beforeEach(() => { - deleteAlertsAndRules(); - createCustomRuleEnabled( - { - ...getNewRule(), - customQuery: 'agent.name:*', - dataSource: { index: ['exceptions*'], type: 'indexPatterns' }, - }, - 'rule_testing', - '1s' - ); - visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL); - goToRuleDetails(); - waitForTheRuleToBeExecuted(); - waitForAlertsToPopulate(); - }); - - afterEach(() => { - esArchiverUnload('exceptions_2'); - }); - - after(() => { - esArchiverUnload('exceptions'); - }); - - it('Creates an exception from an alert and deletes it', () => { - cy.get(ALERTS_COUNT).should('exist'); - cy.get(NUMBER_OF_ALERTS).should('have.text', NUMBER_OF_AUDITBEAT_EXCEPTIONS_ALERTS); - // Create an exception from the alerts actions menu that matches - // the existing alert - addExceptionFromFirstAlert(); - addsException(getException()); - - // Alerts table should now be empty from having added exception and closed - // matching alert - cy.get(EMPTY_ALERT_TABLE).should('exist'); - - // Closed alert should appear in table - goToClosedAlerts(); - cy.get(ALERTS_COUNT).should('exist'); - cy.get(NUMBER_OF_ALERTS).should('have.text', `${NUMBER_OF_AUDITBEAT_EXCEPTIONS_ALERTS}`); - - // Remove the exception and load an event that would have matched that exception - // to show that said exception now starts to show up again - goToExceptionsTab(); - removeException(); - esArchiverLoad('exceptions_2'); - goToAlertsTab(); - goToOpenedAlerts(); - waitForTheRuleToBeExecuted(); - waitForAlertsToPopulate(); - - cy.get(ALERTS_COUNT).should('exist'); - cy.get(NUMBER_OF_ALERTS).should('have.text', `${NUMBER_OF_AUDITBEAT_EXCEPTIONS_ALERTS}`); - }); - - it('Creates an exception from a rule and deletes it', () => { - // Create an exception from the exception tab that matches - // the existing alert - goToExceptionsTab(); - addsExceptionFromRuleSettings(getException()); - - // Alerts table should now be empty from having added exception and closed - // matching alert - goToAlertsTab(); - cy.get(EMPTY_ALERT_TABLE).should('exist'); - - // Closed alert should appear in table - goToClosedAlerts(); - cy.get(ALERTS_COUNT).should('exist'); - cy.get(NUMBER_OF_ALERTS).should('have.text', `${NUMBER_OF_AUDITBEAT_EXCEPTIONS_ALERTS}`); - - // Remove the exception and load an event that would have matched that exception - // to show that said exception now starts to show up again - goToExceptionsTab(); - removeException(); - esArchiverLoad('exceptions_2'); - goToAlertsTab(); - goToOpenedAlerts(); - waitForTheRuleToBeExecuted(); - waitForAlertsToPopulate(); - - cy.get(ALERTS_COUNT).should('exist'); - cy.get(NUMBER_OF_ALERTS).should('have.text', `${NUMBER_OF_AUDITBEAT_EXCEPTIONS_ALERTS}`); - }); - - it('Edits an exception', () => { - goToExceptionsTab(); - addsExceptionFromRuleSettings(getException()); - - editException(); - - // check that the existing item's field is being populated - cy.get(EXCEPTION_ITEM_CONTAINER) - .eq(0) - .find(FIELD_INPUT) - .eq(0) - .should('have.text', 'agent.name'); - - // check that you can select a different field - addExceptionEntryFieldValueOfItemX('user.name{downarrow}{enter}', 0, 0); - addExceptionEntryFieldValueValue('test', 0); - - cy.get(EXCEPTION_EDIT_FLYOUT_SAVE_BTN).click(); - cy.get(EXCEPTION_EDIT_FLYOUT_SAVE_BTN).should('have.attr', 'disabled'); - cy.get(EXCEPTION_EDIT_FLYOUT_SAVE_BTN).should('not.exist'); - }); -}); diff --git a/x-pack/plugins/security_solution/cypress/integration/exceptions/alerts_table_flow/add_exception.spec.ts b/x-pack/plugins/security_solution/cypress/integration/exceptions/alerts_table_flow/add_exception.spec.ts new file mode 100644 index 00000000000000..f1d6d2f1cc063e --- /dev/null +++ b/x-pack/plugins/security_solution/cypress/integration/exceptions/alerts_table_flow/add_exception.spec.ts @@ -0,0 +1,102 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { getException } from '../../../objects/exception'; +import { getNewRule } from '../../../objects/rule'; + +import { ALERTS_COUNT, EMPTY_ALERT_TABLE, NUMBER_OF_ALERTS } from '../../../screens/alerts'; + +import { + addExceptionFromFirstAlert, + goToClosedAlerts, + goToOpenedAlerts, +} from '../../../tasks/alerts'; +import { createCustomRuleEnabled } from '../../../tasks/api_calls/rules'; +import { goToRuleDetails } from '../../../tasks/alerts_detection_rules'; +import { waitForAlertsToPopulate } from '../../../tasks/create_new_rule'; +import { + esArchiverLoad, + esArchiverUnload, + esArchiverResetKibana, +} from '../../../tasks/es_archiver'; +import { login, visitWithoutDateRange } from '../../../tasks/login'; +import { + addsException, + goToAlertsTab, + goToExceptionsTab, + removeException, + waitForTheRuleToBeExecuted, +} from '../../../tasks/rule_details'; + +import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../../urls/navigation'; +import { deleteAlertsAndRules } from '../../../tasks/common'; + +describe('Adds rule exception from alerts flow', () => { + const NUMBER_OF_AUDITBEAT_EXCEPTIONS_ALERTS = '1 alert'; + + before(() => { + esArchiverResetKibana(); + esArchiverLoad('exceptions'); + login(); + }); + + beforeEach(() => { + deleteAlertsAndRules(); + createCustomRuleEnabled( + { + ...getNewRule(), + customQuery: 'agent.name:*', + dataSource: { index: ['exceptions*'], type: 'indexPatterns' }, + }, + 'rule_testing', + '1s' + ); + visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL); + goToRuleDetails(); + waitForTheRuleToBeExecuted(); + waitForAlertsToPopulate(); + }); + + afterEach(() => { + esArchiverUnload('exceptions_2'); + }); + + after(() => { + esArchiverUnload('exceptions'); + }); + + it('Creates an exception from an alert and deletes it', () => { + cy.get(ALERTS_COUNT).should('exist'); + cy.get(NUMBER_OF_ALERTS).should('have.text', NUMBER_OF_AUDITBEAT_EXCEPTIONS_ALERTS); + // Create an exception from the alerts actions menu that matches + // the existing alert + addExceptionFromFirstAlert(); + addsException(getException()); + + // Alerts table should now be empty from having added exception and closed + // matching alert + cy.get(EMPTY_ALERT_TABLE).should('exist'); + + // Closed alert should appear in table + goToClosedAlerts(); + cy.get(ALERTS_COUNT).should('exist'); + cy.get(NUMBER_OF_ALERTS).should('have.text', `${NUMBER_OF_AUDITBEAT_EXCEPTIONS_ALERTS}`); + + // Remove the exception and load an event that would have matched that exception + // to show that said exception now starts to show up again + goToExceptionsTab(); + removeException(); + esArchiverLoad('exceptions_2'); + goToAlertsTab(); + goToOpenedAlerts(); + waitForTheRuleToBeExecuted(); + waitForAlertsToPopulate(); + + cy.get(ALERTS_COUNT).should('exist'); + cy.get(NUMBER_OF_ALERTS).should('have.text', '2 alerts'); + }); +}); diff --git a/x-pack/plugins/security_solution/cypress/integration/exceptions/exceptions_flyout.spec.ts b/x-pack/plugins/security_solution/cypress/integration/exceptions/exceptions_flyout.spec.ts index 8c2e2af4b8badf..dfb018b4bfb5ad 100644 --- a/x-pack/plugins/security_solution/cypress/integration/exceptions/exceptions_flyout.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/exceptions/exceptions_flyout.spec.ts @@ -14,7 +14,7 @@ import { goToRuleDetails } from '../../tasks/alerts_detection_rules'; import { esArchiverLoad, esArchiverResetKibana, esArchiverUnload } from '../../tasks/es_archiver'; import { login, visitWithoutDateRange } from '../../tasks/login'; import { - openExceptionFlyoutFromRuleSettings, + openExceptionFlyoutFromEmptyViewerPrompt, goToExceptionsTab, editException, } from '../../tasks/rule_details'; @@ -34,7 +34,7 @@ import { FIELD_INPUT, LOADING_SPINNER, EXCEPTION_ITEM_CONTAINER, - ADD_EXCEPTIONS_BTN, + ADD_EXCEPTIONS_BTN_FROM_EMPTY_PROMPT_BTN, EXCEPTION_FIELD_LIST, EXCEPTION_EDIT_FLYOUT_SAVE_BTN, EXCEPTION_FLYOUT_VERSION_CONFLICT, @@ -94,7 +94,7 @@ describe('Exceptions flyout', () => { it('Validates empty entry values correctly', () => { cy.root() .pipe(($el) => { - $el.find(ADD_EXCEPTIONS_BTN).trigger('click'); + $el.find(ADD_EXCEPTIONS_BTN_FROM_EMPTY_PROMPT_BTN).trigger('click'); return $el.find(ADD_AND_BTN); }) .should('be.visible'); @@ -123,7 +123,7 @@ describe('Exceptions flyout', () => { it('Does not overwrite values and-ed together', () => { cy.root() .pipe(($el) => { - $el.find(ADD_EXCEPTIONS_BTN).trigger('click'); + $el.find(ADD_EXCEPTIONS_BTN_FROM_EMPTY_PROMPT_BTN).trigger('click'); return $el.find(ADD_AND_BTN); }) .should('be.visible'); @@ -146,7 +146,7 @@ describe('Exceptions flyout', () => { it('Does not overwrite values or-ed together', () => { cy.root() .pipe(($el) => { - $el.find(ADD_EXCEPTIONS_BTN).trigger('click'); + $el.find(ADD_EXCEPTIONS_BTN_FROM_EMPTY_PROMPT_BTN).trigger('click'); return $el.find(ADD_AND_BTN); }) .should('be.visible'); @@ -201,7 +201,7 @@ describe('Exceptions flyout', () => { }); it('Does not overwrite values of nested entry items', () => { - openExceptionFlyoutFromRuleSettings(); + openExceptionFlyoutFromEmptyViewerPrompt(); cy.get(LOADING_SPINNER).should('not.exist'); // exception item 1 @@ -267,7 +267,7 @@ describe('Exceptions flyout', () => { it('Contains custom index fields', () => { cy.root() .pipe(($el) => { - $el.find(ADD_EXCEPTIONS_BTN).trigger('click'); + $el.find(ADD_EXCEPTIONS_BTN_FROM_EMPTY_PROMPT_BTN).trigger('click'); return $el.find(ADD_AND_BTN); }) .should('be.visible'); diff --git a/x-pack/plugins/security_solution/cypress/integration/exceptions/all_exception_lists_read_only.spec.ts b/x-pack/plugins/security_solution/cypress/integration/exceptions/exceptions_management_flow/all_exception_lists_read_only.spec.ts similarity index 70% rename from x-pack/plugins/security_solution/cypress/integration/exceptions/all_exception_lists_read_only.spec.ts rename to x-pack/plugins/security_solution/cypress/integration/exceptions/exceptions_management_flow/all_exception_lists_read_only.spec.ts index e17bc694ab48aa..c1c4fc18960e6a 100644 --- a/x-pack/plugins/security_solution/cypress/integration/exceptions/all_exception_lists_read_only.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/exceptions/exceptions_management_flow/all_exception_lists_read_only.spec.ts @@ -5,14 +5,18 @@ * 2.0. */ -import { ROLES } from '../../../common/test'; -import { getExceptionList } from '../../objects/exception'; -import { EXCEPTIONS_TABLE_SHOWING_LISTS } from '../../screens/exceptions'; -import { createExceptionList } from '../../tasks/api_calls/exceptions'; -import { dismissCallOut, getCallOut, waitForCallOutToBeShown } from '../../tasks/common/callouts'; -import { esArchiverResetKibana } from '../../tasks/es_archiver'; -import { login, visitWithoutDateRange } from '../../tasks/login'; -import { EXCEPTIONS_URL } from '../../urls/navigation'; +import { ROLES } from '../../../../common/test'; +import { getExceptionList } from '../../../objects/exception'; +import { EXCEPTIONS_TABLE_SHOWING_LISTS } from '../../../screens/exceptions'; +import { createExceptionList } from '../../../tasks/api_calls/exceptions'; +import { + dismissCallOut, + getCallOut, + waitForCallOutToBeShown, +} from '../../../tasks/common/callouts'; +import { esArchiverResetKibana } from '../../../tasks/es_archiver'; +import { login, visitWithoutDateRange } from '../../../tasks/login'; +import { EXCEPTIONS_URL } from '../../../urls/navigation'; const MISSING_PRIVILEGES_CALLOUT = 'missing-user-privileges'; diff --git a/x-pack/plugins/security_solution/cypress/integration/exceptions/rule_details_flow/add_exception.spec.ts b/x-pack/plugins/security_solution/cypress/integration/exceptions/rule_details_flow/add_exception.spec.ts new file mode 100644 index 00000000000000..add3f01798129e --- /dev/null +++ b/x-pack/plugins/security_solution/cypress/integration/exceptions/rule_details_flow/add_exception.spec.ts @@ -0,0 +1,221 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { getException, getExceptionList } from '../../../objects/exception'; +import { getNewRule } from '../../../objects/rule'; + +import { ALERTS_COUNT, EMPTY_ALERT_TABLE, NUMBER_OF_ALERTS } from '../../../screens/alerts'; +import { createCustomRule, createCustomRuleEnabled } from '../../../tasks/api_calls/rules'; +import { goToRuleDetails } from '../../../tasks/alerts_detection_rules'; +import { goToClosedAlerts, goToOpenedAlerts } from '../../../tasks/alerts'; +import { + esArchiverLoad, + esArchiverUnload, + esArchiverResetKibana, +} from '../../../tasks/es_archiver'; +import { login, visitWithoutDateRange } from '../../../tasks/login'; +import { + addExceptionFromRuleDetails, + addFirstExceptionFromRuleDetails, + goToAlertsTab, + goToExceptionsTab, + removeException, + searchForExceptionItem, + waitForTheRuleToBeExecuted, +} from '../../../tasks/rule_details'; + +import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../../urls/navigation'; +import { deleteAlertsAndRules } from '../../../tasks/common'; +import { + NO_EXCEPTIONS_EXIST_PROMPT, + EXCEPTION_ITEM_VIEWER_CONTAINER, + NO_EXCEPTIONS_SEARCH_RESULTS_PROMPT, +} from '../../../screens/exceptions'; +import { + createExceptionList, + createExceptionListItem, + deleteExceptionList, +} from '../../../tasks/api_calls/exceptions'; +import { waitForAlertsToPopulate } from '../../../tasks/create_new_rule'; + +describe('Add exception from rule details', () => { + const NUMBER_OF_AUDITBEAT_EXCEPTIONS_ALERTS = '1 alert'; + + before(() => { + esArchiverResetKibana(); + esArchiverLoad('exceptions'); + login(); + }); + + after(() => { + esArchiverUnload('exceptions'); + }); + + describe('rule with existing exceptions', () => { + const exceptionList = getExceptionList(); + beforeEach(() => { + deleteAlertsAndRules(); + deleteExceptionList(exceptionList.list_id, exceptionList.namespace_type); + // create rule with exceptions + createExceptionList(exceptionList, exceptionList.list_id).then((response) => { + createCustomRule( + { + ...getNewRule(), + customQuery: 'agent.name:*', + dataSource: { index: ['exceptions*'], type: 'indexPatterns' }, + exceptionLists: [ + { + id: response.body.id, + list_id: exceptionList.list_id, + type: exceptionList.type, + namespace_type: exceptionList.namespace_type, + }, + ], + }, + '2' + ); + createExceptionListItem(exceptionList.list_id, { + list_id: exceptionList.list_id, + item_id: 'simple_list_item', + tags: [], + type: 'simple', + description: 'Test exception item', + name: 'Sample Exception List Item', + namespace_type: 'single', + entries: [ + { + field: 'user.name', + operator: 'included', + type: 'match_any', + value: ['bar'], + }, + ], + }); + createExceptionListItem(exceptionList.list_id, { + list_id: exceptionList.list_id, + item_id: 'simple_list_item_2', + tags: [], + type: 'simple', + description: 'Test exception item 2', + name: 'Sample Exception List Item 2', + namespace_type: 'single', + entries: [ + { + field: 'unique_value.test', + operator: 'included', + type: 'match_any', + value: ['foo'], + }, + ], + }); + }); + + visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL); + goToRuleDetails(); + goToExceptionsTab(); + }); + + it('Creates an exception item', () => { + // displays existing exception items + cy.get(NO_EXCEPTIONS_EXIST_PROMPT).should('not.exist'); + cy.get(EXCEPTION_ITEM_VIEWER_CONTAINER).should('have.length', 2); + + // clicks prompt button to add a new exception item + addExceptionFromRuleDetails(getException()); + + // new exception item displays + cy.get(EXCEPTION_ITEM_VIEWER_CONTAINER).should('have.length', 3); + }); + + // Trying to figure out with EUI why the search won't trigger + it.skip('Can search for items', () => { + // displays existing exception items + cy.get(NO_EXCEPTIONS_EXIST_PROMPT).should('not.exist'); + cy.get(EXCEPTION_ITEM_VIEWER_CONTAINER).should('have.length', 2); + + // can search for an exception value + searchForExceptionItem('foo'); + + // new exception item displays + cy.get(EXCEPTION_ITEM_VIEWER_CONTAINER).should('have.length', 1); + + // displays empty search result view if no matches found + searchForExceptionItem('abc'); + + // new exception item displays + cy.get(NO_EXCEPTIONS_SEARCH_RESULTS_PROMPT).should('exist'); + }); + }); + + describe('rule without existing exceptions', () => { + beforeEach(() => { + deleteAlertsAndRules(); + createCustomRuleEnabled( + { + ...getNewRule(), + customQuery: 'agent.name:*', + dataSource: { index: ['exceptions*'], type: 'indexPatterns' }, + }, + 'rule_testing', + '1s' + ); + visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL); + goToRuleDetails(); + goToExceptionsTab(); + }); + + afterEach(() => { + esArchiverUnload('exceptions_2'); + }); + + it('Creates an exception item when none exist', () => { + // when no exceptions exist, empty component shows with action to add exception + cy.get(NO_EXCEPTIONS_EXIST_PROMPT).should('exist'); + + // clicks prompt button to add first exception that will also select to close + // all matching alerts + addFirstExceptionFromRuleDetails({ + field: 'agent.name', + operator: 'is', + values: ['foo'], + }); + + // new exception item displays + cy.get(EXCEPTION_ITEM_VIEWER_CONTAINER).should('have.length', 1); + + // Alerts table should now be empty from having added exception and closed + // matching alert + goToAlertsTab(); + cy.get(EMPTY_ALERT_TABLE).should('exist'); + + // Closed alert should appear in table + goToClosedAlerts(); + cy.get(ALERTS_COUNT).should('exist'); + cy.get(NUMBER_OF_ALERTS).should('have.text', `${NUMBER_OF_AUDITBEAT_EXCEPTIONS_ALERTS}`); + + // Remove the exception and load an event that would have matched that exception + // to show that said exception now starts to show up again + goToExceptionsTab(); + + // when removing exception and again, no more exist, empty screen shows again + removeException(); + cy.get(NO_EXCEPTIONS_EXIST_PROMPT).should('exist'); + + // load more docs + esArchiverLoad('exceptions_2'); + + // now that there are no more exceptions, the docs should match and populate alerts + goToAlertsTab(); + goToOpenedAlerts(); + waitForTheRuleToBeExecuted(); + waitForAlertsToPopulate(); + + cy.get(ALERTS_COUNT).should('exist'); + cy.get(NUMBER_OF_ALERTS).should('have.text', '2 alerts'); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/cypress/integration/exceptions/rule_details_flow/add_exception_data_view.spect.ts b/x-pack/plugins/security_solution/cypress/integration/exceptions/rule_details_flow/add_exception_data_view.spect.ts new file mode 100644 index 00000000000000..05b21abe525656 --- /dev/null +++ b/x-pack/plugins/security_solution/cypress/integration/exceptions/rule_details_flow/add_exception_data_view.spect.ts @@ -0,0 +1,114 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { getNewRule } from '../../../objects/rule'; +import { ALERTS_COUNT, EMPTY_ALERT_TABLE, NUMBER_OF_ALERTS } from '../../../screens/alerts'; +import { createCustomRuleEnabled } from '../../../tasks/api_calls/rules'; +import { goToRuleDetails } from '../../../tasks/alerts_detection_rules'; +import { goToClosedAlerts, goToOpenedAlerts } from '../../../tasks/alerts'; +import { + esArchiverLoad, + esArchiverUnload, + esArchiverResetKibana, +} from '../../../tasks/es_archiver'; +import { login, visitWithoutDateRange } from '../../../tasks/login'; +import { + addFirstExceptionFromRuleDetails, + goToAlertsTab, + goToExceptionsTab, + removeException, + waitForTheRuleToBeExecuted, +} from '../../../tasks/rule_details'; + +import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../../urls/navigation'; +import { postDataView, deleteAlertsAndRules } from '../../../tasks/common'; +import { + NO_EXCEPTIONS_EXIST_PROMPT, + EXCEPTION_ITEM_VIEWER_CONTAINER, +} from '../../../screens/exceptions'; +import { waitForAlertsToPopulate } from '../../../tasks/create_new_rule'; + +describe('Add exception using data views from rule details', () => { + const NUMBER_OF_AUDITBEAT_EXCEPTIONS_ALERTS = '1 alert'; + + before(() => { + esArchiverResetKibana(); + esArchiverLoad('exceptions'); + login(); + postDataView('exceptions-*'); + }); + + after(() => { + esArchiverUnload('exceptions'); + }); + + beforeEach(() => { + deleteAlertsAndRules(); + createCustomRuleEnabled( + { + ...getNewRule(), + customQuery: 'agent.name:*', + dataSource: { dataView: 'exceptions-*', type: 'dataView' }, + }, + 'rule_testing', + '1s' + ); + visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL); + goToRuleDetails(); + goToExceptionsTab(); + }); + + afterEach(() => { + esArchiverUnload('exceptions_2'); + }); + + it('Creates an exception item when none exist', () => { + // when no exceptions exist, empty component shows with action to add exception + cy.get(NO_EXCEPTIONS_EXIST_PROMPT).should('exist'); + + // clicks prompt button to add first exception that will also select to close + // all matching alerts + addFirstExceptionFromRuleDetails({ + field: 'agent.name', + operator: 'is', + values: ['foo'], + }); + + // new exception item displays + cy.get(EXCEPTION_ITEM_VIEWER_CONTAINER).should('have.length', 1); + + // Alerts table should now be empty from having added exception and closed + // matching alert + goToAlertsTab(); + cy.get(EMPTY_ALERT_TABLE).should('exist'); + + // Closed alert should appear in table + goToClosedAlerts(); + cy.get(ALERTS_COUNT).should('exist'); + cy.get(NUMBER_OF_ALERTS).should('have.text', `${NUMBER_OF_AUDITBEAT_EXCEPTIONS_ALERTS}`); + + // Remove the exception and load an event that would have matched that exception + // to show that said exception now starts to show up again + goToExceptionsTab(); + + // when removing exception and again, no more exist, empty screen shows again + removeException(); + cy.get(NO_EXCEPTIONS_EXIST_PROMPT).should('exist'); + + // load more docs + esArchiverLoad('exceptions_2'); + + // now that there are no more exceptions, the docs should match and populate alerts + goToAlertsTab(); + goToOpenedAlerts(); + waitForTheRuleToBeExecuted(); + waitForAlertsToPopulate(); + + cy.get(ALERTS_COUNT).should('exist'); + cy.get(NUMBER_OF_ALERTS).should('have.text', '2 alerts'); + }); +}); diff --git a/x-pack/plugins/security_solution/cypress/integration/exceptions/rule_details_flow/edit_exception.spec.ts b/x-pack/plugins/security_solution/cypress/integration/exceptions/rule_details_flow/edit_exception.spec.ts new file mode 100644 index 00000000000000..26763c9efeebc8 --- /dev/null +++ b/x-pack/plugins/security_solution/cypress/integration/exceptions/rule_details_flow/edit_exception.spec.ts @@ -0,0 +1,154 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { getExceptionList } from '../../../objects/exception'; +import { getNewRule } from '../../../objects/rule'; + +import { createCustomRuleEnabled } from '../../../tasks/api_calls/rules'; +import { goToRuleDetails } from '../../../tasks/alerts_detection_rules'; +import { goToOpenedAlerts } from '../../../tasks/alerts'; +import { + esArchiverLoad, + esArchiverUnload, + esArchiverResetKibana, +} from '../../../tasks/es_archiver'; +import { login, visitWithoutDateRange } from '../../../tasks/login'; +import { + goToExceptionsTab, + waitForTheRuleToBeExecuted, + editException, + goToAlertsTab, +} from '../../../tasks/rule_details'; + +import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../../urls/navigation'; +import { deleteAlertsAndRules } from '../../../tasks/common'; +import { + EXCEPTION_EDIT_FLYOUT_SAVE_BTN, + EXCEPTION_ITEM_VIEWER_CONTAINER, + EXCEPTION_ITEM_CONTAINER, + FIELD_INPUT, +} from '../../../screens/exceptions'; +import { + createExceptionList, + createExceptionListItem, + deleteExceptionList, +} from '../../../tasks/api_calls/exceptions'; +import { waitForAlertsToPopulate } from '../../../tasks/create_new_rule'; +import { + addExceptionEntryFieldValueOfItemX, + addExceptionEntryFieldValueValue, +} from '../../../tasks/exceptions'; +import { ALERTS_COUNT, NUMBER_OF_ALERTS } from '../../../screens/alerts'; + +describe('Edit exception from rule details', () => { + const exceptionList = getExceptionList(); + const NUMBER_OF_AUDITBEAT_EXCEPTIONS_ALERTS = '1 alert'; + + before(() => { + esArchiverResetKibana(); + esArchiverLoad('exceptions'); + login(); + }); + + after(() => { + esArchiverUnload('exceptions'); + }); + + beforeEach(() => { + deleteAlertsAndRules(); + deleteExceptionList(exceptionList.list_id, exceptionList.namespace_type); + // create rule with exceptions + createExceptionList(exceptionList, exceptionList.list_id).then((response) => { + createCustomRuleEnabled( + { + ...getNewRule(), + customQuery: 'agent.name:*', + dataSource: { index: ['exceptions*'], type: 'indexPatterns' }, + exceptionLists: [ + { + id: response.body.id, + list_id: exceptionList.list_id, + type: exceptionList.type, + namespace_type: exceptionList.namespace_type, + }, + ], + }, + '2', + '2s' + ); + createExceptionListItem(exceptionList.list_id, { + list_id: exceptionList.list_id, + item_id: 'simple_list_item', + tags: [], + type: 'simple', + description: 'Test exception item', + name: 'Sample Exception List Item', + namespace_type: 'single', + entries: [ + { + field: 'unique_value.test', + operator: 'included', + type: 'match_any', + value: ['bar'], + }, + ], + }); + }); + + visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL); + goToRuleDetails(); + waitForTheRuleToBeExecuted(); + waitForAlertsToPopulate(); + goToExceptionsTab(); + }); + + afterEach(() => { + esArchiverUnload('exceptions_2'); + }); + + it('Edits an exception item', () => { + // displays existing exception item + cy.get(EXCEPTION_ITEM_VIEWER_CONTAINER).should('have.length', 1); + + editException(); + + // check that the existing item's field is being populated + cy.get(EXCEPTION_ITEM_CONTAINER) + .eq(0) + .find(FIELD_INPUT) + .eq(0) + .should('have.text', 'unique_value.test'); + + // check that you can select a different field + addExceptionEntryFieldValueOfItemX('agent.name{downarrow}{enter}', 0, 0); + addExceptionEntryFieldValueValue('foo', 0); + + cy.get(EXCEPTION_EDIT_FLYOUT_SAVE_BTN).click(); + cy.get(EXCEPTION_EDIT_FLYOUT_SAVE_BTN).should('have.attr', 'disabled'); + cy.get(EXCEPTION_EDIT_FLYOUT_SAVE_BTN).should('not.exist'); + cy.get(EXCEPTION_ITEM_VIEWER_CONTAINER).should('have.length', 1); + + // Alerts table should still show single alert + goToAlertsTab(); + cy.get(ALERTS_COUNT).should('exist'); + cy.get(NUMBER_OF_ALERTS).should('have.text', `${NUMBER_OF_AUDITBEAT_EXCEPTIONS_ALERTS}`); + + // load more docs + esArchiverLoad('exceptions_2'); + + // now that 2 more docs have been added, one should match the edited exception + goToAlertsTab(); + goToOpenedAlerts(); + waitForTheRuleToBeExecuted(); + waitForAlertsToPopulate(2); + + // there should be 2 alerts, one is the original alert and the second is for the newly + // matching doc + cy.get(ALERTS_COUNT).should('exist'); + cy.get(NUMBER_OF_ALERTS).should('have.text', '2 alerts'); + }); +}); diff --git a/x-pack/plugins/security_solution/cypress/integration/exceptions/rule_details_flow/edit_exception_data_view.spec.ts b/x-pack/plugins/security_solution/cypress/integration/exceptions/rule_details_flow/edit_exception_data_view.spec.ts new file mode 100644 index 00000000000000..b5178615aa5818 --- /dev/null +++ b/x-pack/plugins/security_solution/cypress/integration/exceptions/rule_details_flow/edit_exception_data_view.spec.ts @@ -0,0 +1,155 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { getExceptionList } from '../../../objects/exception'; +import { getNewRule } from '../../../objects/rule'; + +import { createCustomRuleEnabled } from '../../../tasks/api_calls/rules'; +import { goToRuleDetails } from '../../../tasks/alerts_detection_rules'; +import { goToOpenedAlerts } from '../../../tasks/alerts'; +import { + esArchiverLoad, + esArchiverUnload, + esArchiverResetKibana, +} from '../../../tasks/es_archiver'; +import { login, visitWithoutDateRange } from '../../../tasks/login'; +import { + goToExceptionsTab, + waitForTheRuleToBeExecuted, + editException, + goToAlertsTab, +} from '../../../tasks/rule_details'; + +import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../../urls/navigation'; +import { postDataView, deleteAlertsAndRules } from '../../../tasks/common'; +import { + EXCEPTION_EDIT_FLYOUT_SAVE_BTN, + EXCEPTION_ITEM_VIEWER_CONTAINER, + EXCEPTION_ITEM_CONTAINER, + FIELD_INPUT, +} from '../../../screens/exceptions'; +import { + createExceptionList, + createExceptionListItem, + deleteExceptionList, +} from '../../../tasks/api_calls/exceptions'; +import { waitForAlertsToPopulate } from '../../../tasks/create_new_rule'; +import { + addExceptionEntryFieldValueOfItemX, + addExceptionEntryFieldValueValue, +} from '../../../tasks/exceptions'; +import { ALERTS_COUNT, NUMBER_OF_ALERTS } from '../../../screens/alerts'; + +describe('Edit exception using data views from rule details', () => { + const exceptionList = getExceptionList(); + const NUMBER_OF_AUDITBEAT_EXCEPTIONS_ALERTS = '1 alert'; + + before(() => { + esArchiverResetKibana(); + esArchiverLoad('exceptions'); + login(); + postDataView('exceptions-*'); + }); + + after(() => { + esArchiverUnload('exceptions'); + }); + + beforeEach(() => { + deleteAlertsAndRules(); + deleteExceptionList(exceptionList.list_id, exceptionList.namespace_type); + // create rule with exceptions + createExceptionList(exceptionList, exceptionList.list_id).then((response) => { + createCustomRuleEnabled( + { + ...getNewRule(), + customQuery: 'agent.name:*', + dataSource: { dataView: 'exceptions-*', type: 'dataView' }, + exceptionLists: [ + { + id: response.body.id, + list_id: exceptionList.list_id, + type: exceptionList.type, + namespace_type: exceptionList.namespace_type, + }, + ], + }, + '2', + '2s' + ); + createExceptionListItem(exceptionList.list_id, { + list_id: exceptionList.list_id, + item_id: 'simple_list_item', + tags: [], + type: 'simple', + description: 'Test exception item', + name: 'Sample Exception List Item', + namespace_type: 'single', + entries: [ + { + field: 'unique_value.test', + operator: 'included', + type: 'match_any', + value: ['bar'], + }, + ], + }); + }); + + visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL); + goToRuleDetails(); + waitForTheRuleToBeExecuted(); + waitForAlertsToPopulate(); + goToExceptionsTab(); + }); + + afterEach(() => { + esArchiverUnload('exceptions_2'); + }); + + it('Edits an exception item', () => { + // displays existing exception item + cy.get(EXCEPTION_ITEM_VIEWER_CONTAINER).should('have.length', 1); + + editException(); + + // check that the existing item's field is being populated + cy.get(EXCEPTION_ITEM_CONTAINER) + .eq(0) + .find(FIELD_INPUT) + .eq(0) + .should('have.text', 'unique_value.test'); + + // check that you can select a different field + addExceptionEntryFieldValueOfItemX('agent.name{downarrow}{enter}', 0, 0); + addExceptionEntryFieldValueValue('foo', 0); + + cy.get(EXCEPTION_EDIT_FLYOUT_SAVE_BTN).click(); + cy.get(EXCEPTION_EDIT_FLYOUT_SAVE_BTN).should('have.attr', 'disabled'); + cy.get(EXCEPTION_EDIT_FLYOUT_SAVE_BTN).should('not.exist'); + cy.get(EXCEPTION_ITEM_VIEWER_CONTAINER).should('have.length', 1); + + // Alerts table should still show single alert + goToAlertsTab(); + cy.get(ALERTS_COUNT).should('exist'); + cy.get(NUMBER_OF_ALERTS).should('have.text', `${NUMBER_OF_AUDITBEAT_EXCEPTIONS_ALERTS}`); + + // load more docs + esArchiverLoad('exceptions_2'); + + // now that 2 more docs have been added, one should match the edited exception + goToAlertsTab(); + goToOpenedAlerts(); + waitForTheRuleToBeExecuted(); + waitForAlertsToPopulate(2); + + // there should be 2 alerts, one is the original alert and the second is for the newly + // matching doc + cy.get(ALERTS_COUNT).should('exist'); + cy.get(NUMBER_OF_ALERTS).should('have.text', '2 alerts'); + }); +}); diff --git a/x-pack/plugins/security_solution/cypress/integration/exceptions/rule_details_flow/read_only_view.spect.ts b/x-pack/plugins/security_solution/cypress/integration/exceptions/rule_details_flow/read_only_view.spect.ts new file mode 100644 index 00000000000000..b11c688520b1a3 --- /dev/null +++ b/x-pack/plugins/security_solution/cypress/integration/exceptions/rule_details_flow/read_only_view.spect.ts @@ -0,0 +1,107 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { getExceptionList } from '../../../objects/exception'; +import { getNewRule } from '../../../objects/rule'; +import { ROLES } from '../../../../common/test'; +import { createCustomRule } from '../../../tasks/api_calls/rules'; +import { esArchiverResetKibana } from '../../../tasks/es_archiver'; +import { login, visitWithoutDateRange } from '../../../tasks/login'; +import { goToExceptionsTab, goToAlertsTab } from '../../../tasks/rule_details'; +import { goToRuleDetails } from '../../../tasks/alerts_detection_rules'; +import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../../urls/navigation'; +import { deleteAlertsAndRules } from '../../../tasks/common'; +import { + NO_EXCEPTIONS_EXIST_PROMPT, + EXCEPTION_ITEM_VIEWER_CONTAINER, + ADD_EXCEPTIONS_BTN_FROM_VIEWER_HEADER, + ADD_EXCEPTIONS_BTN_FROM_EMPTY_PROMPT_BTN, +} from '../../../screens/exceptions'; +import { EXCEPTION_ITEM_ACTIONS_BUTTON } from '../../../screens/rule_details'; +import { + createExceptionList, + createExceptionListItem, + deleteExceptionList, +} from '../../../tasks/api_calls/exceptions'; + +describe('Exceptions viewer read only', () => { + const exceptionList = getExceptionList(); + + before(() => { + esArchiverResetKibana(); + // create rule with exceptions + createExceptionList(exceptionList, exceptionList.list_id).then((response) => { + createCustomRule( + { + ...getNewRule(), + customQuery: 'agent.name:*', + dataSource: { index: ['exceptions*'], type: 'indexPatterns' }, + exceptionLists: [ + { + id: response.body.id, + list_id: exceptionList.list_id, + type: exceptionList.type, + namespace_type: exceptionList.namespace_type, + }, + ], + }, + '2' + ); + }); + + login(ROLES.reader); + visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL, ROLES.reader); + goToRuleDetails(); + goToExceptionsTab(); + }); + + after(() => { + deleteAlertsAndRules(); + deleteExceptionList(exceptionList.list_id, exceptionList.namespace_type); + }); + + it('Cannot add an exception from empty viewer screen', () => { + // when no exceptions exist, empty component shows with action to add exception + cy.get(NO_EXCEPTIONS_EXIST_PROMPT).should('exist'); + + // cannot add an exception from empty view + cy.get(ADD_EXCEPTIONS_BTN_FROM_EMPTY_PROMPT_BTN).should('have.attr', 'disabled'); + }); + + it('Cannot take actions on exception', () => { + createExceptionListItem(exceptionList.list_id, { + list_id: exceptionList.list_id, + item_id: 'simple_list_item', + tags: [], + type: 'simple', + description: 'Test exception item', + name: 'Sample Exception List Item', + namespace_type: 'single', + entries: [ + { + field: 'unique_value.test', + operator: 'included', + type: 'match_any', + value: ['bar'], + }, + ], + }); + + goToAlertsTab(); + goToExceptionsTab(); + + // can view exceptions + cy.get(NO_EXCEPTIONS_EXIST_PROMPT).should('not.exist'); + cy.get(EXCEPTION_ITEM_VIEWER_CONTAINER).should('have.length', 1); + + // cannot access edit/delete actions of item + cy.get(EXCEPTION_ITEM_ACTIONS_BUTTON).should('have.attr', 'disabled'); + + // does not display add exception button + cy.get(ADD_EXCEPTIONS_BTN_FROM_VIEWER_HEADER).should('not.exist'); + }); +}); diff --git a/x-pack/plugins/security_solution/cypress/screens/exceptions.ts b/x-pack/plugins/security_solution/cypress/screens/exceptions.ts index a02a318bfb307e..1ca8ded9463005 100644 --- a/x-pack/plugins/security_solution/cypress/screens/exceptions.ts +++ b/x-pack/plugins/security_solution/cypress/screens/exceptions.ts @@ -5,8 +5,6 @@ * 2.0. */ -export const ADD_EXCEPTIONS_BTN = '[data-test-subj="exceptionsHeaderAddExceptionBtn"]'; - export const CLOSE_ALERTS_CHECKBOX = '[data-test-subj="bulk-close-alert-on-add-add-exception-checkbox"]'; @@ -67,3 +65,20 @@ export const EXCEPTION_FLYOUT_VERSION_CONFLICT = '[data-test-subj="exceptionsFlyoutVersionConflict"]'; export const EXCEPTION_FLYOUT_LIST_DELETED_ERROR = '[data-test-subj="errorCalloutContainer"]'; + +// Exceptions all items view +export const NO_EXCEPTIONS_EXIST_PROMPT = + '[data-test-subj="exceptionItemViewerEmptyPrompts-empty-detection"]'; + +export const ADD_EXCEPTIONS_BTN_FROM_EMPTY_PROMPT_BTN = + '[data-test-subj="exceptionsEmptyPromptButton"]'; + +export const EXCEPTION_ITEM_VIEWER_CONTAINER = '[data-test-subj="exceptionItemContainer"]'; + +export const ADD_EXCEPTIONS_BTN_FROM_VIEWER_HEADER = + '[data-test-subj="exceptionsHeaderAddExceptionBtn"]'; + +export const NO_EXCEPTIONS_SEARCH_RESULTS_PROMPT = + '[data-test-subj="exceptionItemViewerEmptyPrompts-emptySearch"]'; + +export const EXCEPTION_ITEM_VIEWER_SEARCH = 'input[data-test-subj="exceptionsViewerSearchBar"]'; diff --git a/x-pack/plugins/security_solution/cypress/screens/rule_details.ts b/x-pack/plugins/security_solution/cypress/screens/rule_details.ts index 989353cf7a2532..80883d825c18f6 100644 --- a/x-pack/plugins/security_solution/cypress/screens/rule_details.ts +++ b/x-pack/plugins/security_solution/cypress/screens/rule_details.ts @@ -31,7 +31,7 @@ export const DETAILS_DESCRIPTION = '.euiDescriptionList__description'; export const DETAILS_TITLE = '.euiDescriptionList__title'; -export const EXCEPTIONS_TAB = '[data-test-subj="navigation-rule_exceptions"]'; +export const EXCEPTIONS_TAB = 'a[data-test-subj="navigation-rule_exceptions"]'; export const FALSE_POSITIVES_DETAILS = 'False positive examples'; diff --git a/x-pack/plugins/security_solution/cypress/tasks/api_calls/rules.ts b/x-pack/plugins/security_solution/cypress/tasks/api_calls/rules.ts index cb2fc257f7dc77..afee74e1a943b4 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/api_calls/rules.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/api_calls/rules.ts @@ -218,6 +218,7 @@ export const createCustomRuleEnabled = ( query: rule.customQuery, language: 'kuery', enabled: true, + exceptions_list: rule.exceptionLists ?? [], tags: ['rule1'], max_signals: maxSignals, building_block_type: rule.buildingBlockType, @@ -243,6 +244,7 @@ export const createCustomRuleEnabled = ( query: rule.customQuery, language: 'kuery', enabled: true, + exceptions_list: rule.exceptionLists ?? [], tags: ['rule1'], max_signals: maxSignals, building_block_type: rule.buildingBlockType, diff --git a/x-pack/plugins/security_solution/cypress/tasks/rule_details.ts b/x-pack/plugins/security_solution/cypress/tasks/rule_details.ts index dcc4163fa9bf57..1cec924eae55a4 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/rule_details.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/rule_details.ts @@ -8,9 +8,11 @@ import type { Exception } from '../objects/exception'; import { RULE_STATUS } from '../screens/create_new_rule'; import { - ADD_EXCEPTIONS_BTN, + ADD_EXCEPTIONS_BTN_FROM_EMPTY_PROMPT_BTN, + ADD_EXCEPTIONS_BTN_FROM_VIEWER_HEADER, CLOSE_ALERTS_CHECKBOX, CONFIRM_BTN, + EXCEPTION_ITEM_VIEWER_SEARCH, FIELD_INPUT, LOADING_SPINNER, OPERATOR_INPUT, @@ -65,14 +67,48 @@ export const addsFieldsToTimeline = (search: string, fields: string[]) => { closeFieldsBrowser(); }; -export const openExceptionFlyoutFromRuleSettings = () => { - cy.get(ADD_EXCEPTIONS_BTN).click(); - cy.get(LOADING_SPINNER).should('not.exist'); - cy.get(FIELD_INPUT).should('be.visible'); +export const openExceptionFlyoutFromEmptyViewerPrompt = () => { + cy.root() + .pipe(($el) => { + $el.find(ADD_EXCEPTIONS_BTN_FROM_EMPTY_PROMPT_BTN).trigger('click'); + return $el.find(FIELD_INPUT); + }) + .should('be.visible'); +}; + +export const searchForExceptionItem = (query: string) => { + cy.get(EXCEPTION_ITEM_VIEWER_SEARCH).type(`${query}`).trigger('keydown', { + key: 'Enter', + keyCode: 13, + code: 'Enter', + type: 'keydown', + }); +}; + +export const addExceptionFlyoutFromViewerHeader = () => { + cy.root() + .pipe(($el) => { + $el.find(ADD_EXCEPTIONS_BTN_FROM_VIEWER_HEADER).trigger('click'); + return $el.find(FIELD_INPUT); + }) + .should('be.visible'); +}; + +export const addExceptionFromRuleDetails = (exception: Exception) => { + addExceptionFlyoutFromViewerHeader(); + cy.get(FIELD_INPUT).type(`${exception.field}{downArrow}{enter}`); + cy.get(OPERATOR_INPUT).type(`${exception.operator}{enter}`); + exception.values.forEach((value) => { + cy.get(VALUES_INPUT).type(`${value}{enter}`); + }); + cy.get(CLOSE_ALERTS_CHECKBOX).click({ force: true }); + cy.get(CONFIRM_BTN).click(); + cy.get(CONFIRM_BTN).should('have.attr', 'disabled'); + cy.get(CONFIRM_BTN).should('not.exist'); }; -export const addsExceptionFromRuleSettings = (exception: Exception) => { - openExceptionFlyoutFromRuleSettings(); +export const addFirstExceptionFromRuleDetails = (exception: Exception) => { + openExceptionFlyoutFromEmptyViewerPrompt(); cy.get(FIELD_INPUT).type(`${exception.field}{downArrow}{enter}`); cy.get(OPERATOR_INPUT).type(`${exception.operator}{enter}`); exception.values.forEach((value) => { @@ -89,13 +125,14 @@ export const goToAlertsTab = () => { }; export const goToExceptionsTab = () => { + cy.get(EXCEPTIONS_TAB).should('exist'); cy.get(EXCEPTIONS_TAB).click(); }; export const editException = () => { - cy.get(EXCEPTION_ITEM_ACTIONS_BUTTON).click({ force: true }); + cy.get(EXCEPTION_ITEM_ACTIONS_BUTTON).eq(0).click({ force: true }); - cy.get(EDIT_EXCEPTION_BTN).click({ force: true }); + cy.get(EDIT_EXCEPTION_BTN).eq(0).click({ force: true }); }; export const removeException = () => { diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/translations.ts b/x-pack/plugins/security_solution/public/common/components/exceptions/translations.ts deleted file mode 100644 index 2372e063b48cf3..00000000000000 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/translations.ts +++ /dev/null @@ -1,266 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { i18n } from '@kbn/i18n'; - -export const DETECTION_LIST = i18n.translate( - 'xpack.securitySolution.exceptions.detectionListLabel', - { - defaultMessage: 'Detection list', - } -); - -export const ENDPOINT_LIST = i18n.translate('xpack.securitySolution.exceptions.endpointListLabel', { - defaultMessage: 'Endpoint list', -}); - -export const EDIT = i18n.translate('xpack.securitySolution.exceptions.editButtonLabel', { - defaultMessage: 'Edit', -}); - -export const REMOVE = i18n.translate('xpack.securitySolution.exceptions.removeButtonLabel', { - defaultMessage: 'Remove', -}); - -export const COMMENTS_SHOW = (comments: number) => - i18n.translate('xpack.securitySolution.exceptions.showCommentsLabel', { - values: { comments }, - defaultMessage: 'Show ({comments}) {comments, plural, =1 {Comment} other {Comments}}', - }); - -export const COMMENTS_HIDE = (comments: number) => - i18n.translate('xpack.securitySolution.exceptions.hideCommentsLabel', { - values: { comments }, - defaultMessage: 'Hide ({comments}) {comments, plural, =1 {Comment} other {Comments}}', - }); - -export const NAME = i18n.translate('xpack.securitySolution.exceptions.nameLabel', { - defaultMessage: 'Name', -}); - -export const COMMENT = i18n.translate('xpack.securitySolution.exceptions.commentLabel', { - defaultMessage: 'Comment', -}); - -export const COMMENT_EVENT = i18n.translate('xpack.securitySolution.exceptions.commentEventLabel', { - defaultMessage: 'added a comment', -}); - -export const OPERATING_SYSTEM_LABEL = i18n.translate( - 'xpack.securitySolution.exceptions.operatingSystemFullLabel', - { - defaultMessage: 'Operating System', - } -); - -export const SEARCH_DEFAULT = i18n.translate( - 'xpack.securitySolution.exceptions.viewer.searchDefaultPlaceholder', - { - defaultMessage: 'Search field (ex: host.name)', - } -); - -export const ADD_EXCEPTION_LABEL = i18n.translate( - 'xpack.securitySolution.exceptions.viewer.addExceptionLabel', - { - defaultMessage: 'Add new exception', - } -); - -export const ADD_TO_ENDPOINT_LIST = i18n.translate( - 'xpack.securitySolution.exceptions.viewer.addToEndpointListLabel', - { - defaultMessage: 'Add Endpoint exception', - } -); - -export const ADD_TO_DETECTIONS_LIST = i18n.translate( - 'xpack.securitySolution.exceptions.viewer.addToDetectionsListLabel', - { - defaultMessage: 'Add rule exception', - } -); - -export const EXCEPTION_EMPTY_PROMPT_TITLE = i18n.translate( - 'xpack.securitySolution.exceptions.viewer.emptyPromptTitle', - { - defaultMessage: 'This rule has no exceptions', - } -); - -export const EXCEPTION_NO_SEARCH_RESULTS_PROMPT_BODY = i18n.translate( - 'xpack.securitySolution.exceptions.viewer.noSearchResultsPromptBody', - { - defaultMessage: 'No search results found.', - } -); - -export const EXCEPTION_EMPTY_PROMPT_BODY = i18n.translate( - 'xpack.securitySolution.exceptions.viewer.emptyPromptBody', - { - defaultMessage: - 'You can add exceptions to fine tune the rule so that detection alerts are not created when exception conditions are met. Exceptions improve detection accuracy, which can help reduce the number of false positives.', - } -); - -export const FETCH_LIST_ERROR = i18n.translate( - 'xpack.securitySolution.exceptions.viewer.fetchingListError', - { - defaultMessage: 'Error fetching exceptions', - } -); - -export const DELETE_EXCEPTION_ERROR = i18n.translate( - 'xpack.securitySolution.exceptions.viewer.deleteExceptionError', - { - defaultMessage: 'Error deleting exception', - } -); - -export const ITEMS_PER_PAGE = (items: number) => - i18n.translate('xpack.securitySolution.exceptions.exceptionsPaginationLabel', { - values: { items }, - defaultMessage: 'Items per page: {items}', - }); - -export const NUMBER_OF_ITEMS = (items: number) => - i18n.translate('xpack.securitySolution.exceptions.paginationNumberOfItemsLabel', { - values: { items }, - defaultMessage: '{items} items', - }); - -export const REFRESH = i18n.translate('xpack.securitySolution.exceptions.utilityRefreshLabel', { - defaultMessage: 'Refresh', -}); - -export const SHOWING_EXCEPTIONS = (items: number) => - i18n.translate('xpack.securitySolution.exceptions.utilityNumberExceptionsLabel', { - values: { items }, - defaultMessage: 'Showing {items} {items, plural, =1 {exception} other {exceptions}}', - }); - -export const FIELD = i18n.translate('xpack.securitySolution.exceptions.fieldDescription', { - defaultMessage: 'Field', -}); - -export const OPERATOR = i18n.translate('xpack.securitySolution.exceptions.operatorDescription', { - defaultMessage: 'Operator', -}); - -export const VALUE = i18n.translate('xpack.securitySolution.exceptions.valueDescription', { - defaultMessage: 'Value', -}); - -export const AND = i18n.translate('xpack.securitySolution.exceptions.andDescription', { - defaultMessage: 'AND', -}); - -export const OR = i18n.translate('xpack.securitySolution.exceptions.orDescription', { - defaultMessage: 'OR', -}); - -export const ADD_COMMENT_PLACEHOLDER = i18n.translate( - 'xpack.securitySolution.exceptions.viewer.addCommentPlaceholder', - { - defaultMessage: 'Add a new comment...', - } -); - -export const ADD_TO_CLIPBOARD = i18n.translate( - 'xpack.securitySolution.exceptions.viewer.addToClipboard', - { - defaultMessage: 'Comment', - } -); - -export const DESCRIPTION = i18n.translate('xpack.securitySolution.exceptions.descriptionLabel', { - defaultMessage: 'Description', -}); - -export const TOTAL_ITEMS_FETCH_ERROR = i18n.translate( - 'xpack.securitySolution.exceptions.viewer.fetchTotalsError', - { - defaultMessage: 'Error getting exception item totals', - } -); - -export const CLEAR_EXCEPTIONS_LABEL = i18n.translate( - 'xpack.securitySolution.exceptions.clearExceptionsLabel', - { - defaultMessage: 'Remove Exception List', - } -); - -export const ADD_EXCEPTION_FETCH_404_ERROR = (listId: string) => - i18n.translate('xpack.securitySolution.exceptions.fetch404Error', { - values: { listId }, - defaultMessage: - 'The associated exception list ({listId}) no longer exists. Please remove the missing exception list to add additional exceptions to the detection rule.', - }); - -export const ADD_EXCEPTION_FETCH_ERROR = i18n.translate( - 'xpack.securitySolution.exceptions.fetchError', - { - defaultMessage: 'Error fetching exception list', - } -); - -export const ERROR = i18n.translate('xpack.securitySolution.exceptions.errorLabel', { - defaultMessage: 'Error', -}); - -export const CANCEL = i18n.translate('xpack.securitySolution.exceptions.cancelLabel', { - defaultMessage: 'Cancel', -}); - -export const MODAL_ERROR_ACCORDION_TEXT = i18n.translate( - 'xpack.securitySolution.exceptions.modalErrorAccordionText', - { - defaultMessage: 'Show rule reference information:', - } -); - -export const DISSASOCIATE_LIST_SUCCESS = (id: string) => - i18n.translate('xpack.securitySolution.exceptions.dissasociateListSuccessText', { - values: { id }, - defaultMessage: 'Exception list ({id}) has successfully been removed', - }); - -export const DISSASOCIATE_EXCEPTION_LIST_ERROR = i18n.translate( - 'xpack.securitySolution.exceptions.dissasociateExceptionListError', - { - defaultMessage: 'Failed to remove exception list', - } -); - -export const OPERATING_SYSTEM_WINDOWS = i18n.translate( - 'xpack.securitySolution.exceptions.operatingSystemWindows', - { - defaultMessage: 'Windows', - } -); - -export const OPERATING_SYSTEM_MAC = i18n.translate( - 'xpack.securitySolution.exceptions.operatingSystemMac', - { - defaultMessage: 'macOS', - } -); - -export const OPERATING_SYSTEM_WINDOWS_AND_MAC = i18n.translate( - 'xpack.securitySolution.exceptions.operatingSystemWindowsAndMac', - { - defaultMessage: 'Windows and macOS', - } -); - -export const OPERATING_SYSTEM_LINUX = i18n.translate( - 'xpack.securitySolution.exceptions.operatingSystemLinux', - { - defaultMessage: 'Linux', - } -); diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item_card/exception_item_card_meta.test.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item_card/exception_item_card_meta.test.tsx deleted file mode 100644 index b5a24ef3e472df..00000000000000 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item_card/exception_item_card_meta.test.tsx +++ /dev/null @@ -1,51 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { mount } from 'enzyme'; -import { getExceptionListItemSchemaMock } from '@kbn/lists-plugin/common/schemas/response/exception_list_item_schema.mock'; - -import { TestProviders } from '../../../../mock'; -import { ExceptionItemCardMetaInfo } from './exception_item_card_meta'; - -describe('ExceptionItemCardMetaInfo', () => { - it('it renders item creation info', () => { - const wrapper = mount( - - - - ); - - expect( - wrapper.find('[data-test-subj="exceptionItemMeta-createdBy-value1"]').at(0).text() - ).toEqual('Apr 20, 2020 @ 15:25:31.830'); - expect( - wrapper.find('[data-test-subj="exceptionItemMeta-createdBy-value2"]').at(0).text() - ).toEqual('some user'); - }); - - it('it renders item update info', () => { - const wrapper = mount( - - - - ); - - expect( - wrapper.find('[data-test-subj="exceptionItemMeta-updatedBy-value1"]').at(0).text() - ).toEqual('Apr 20, 2020 @ 15:25:31.830'); - expect( - wrapper.find('[data-test-subj="exceptionItemMeta-updatedBy-value2"]').at(0).text() - ).toEqual('some user'); - }); -}); diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item_card/exception_item_card_meta.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item_card/exception_item_card_meta.tsx deleted file mode 100644 index 3e9cf5e68d95ee..00000000000000 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item_card/exception_item_card_meta.tsx +++ /dev/null @@ -1,111 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { memo } from 'react'; -import { EuiAvatar, EuiBadge, EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui'; -import type { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; -import styled from 'styled-components'; - -import * as i18n from './translations'; -import { FormattedDate, FormattedRelativePreferenceDate } from '../../../formatted_date'; - -const StyledCondition = styled('div')` - padding-top: 4px !important; -`; -export interface ExceptionItemCardMetaInfoProps { - item: ExceptionListItemSchema; - dataTestSubj: string; -} - -export const ExceptionItemCardMetaInfo = memo( - ({ item, dataTestSubj }) => { - return ( - - - } - value2={item.created_by} - dataTestSubj={`${dataTestSubj}-createdBy`} - /> - - - - - - } - value2={item.updated_by} - dataTestSubj={`${dataTestSubj}-updatedBy`} - /> - - - ); - } -); -ExceptionItemCardMetaInfo.displayName = 'ExceptionItemCardMetaInfo'; - -interface MetaInfoDetailsProps { - fieldName: string; - label: string; - value1: JSX.Element | string; - value2: string; - dataTestSubj: string; -} - -const MetaInfoDetails = memo(({ label, value1, value2, dataTestSubj }) => { - return ( - - - - {label} - - - - - {value1} - - - - - {i18n.EXCEPTION_ITEM_META_BY} - - - - - - - - - - {value2} - - - - - - ); -}); - -MetaInfoDetails.displayName = 'MetaInfoDetails'; diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_pagination.test.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_pagination.test.tsx deleted file mode 100644 index 4d38fac3407278..00000000000000 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_pagination.test.tsx +++ /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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { mount } from 'enzyme'; - -import { ExceptionsViewerPagination } from './exceptions_pagination'; - -describe('ExceptionsViewerPagination', () => { - it('it renders passed in "pageSize" as selected option', () => { - const wrapper = mount( - - ); - - expect(wrapper.find('[data-test-subj="exceptionsPerPageBtn"]').at(0).text()).toEqual( - 'Items per page: 50' - ); - }); - - it('it renders all passed in page size options when per page button clicked', () => { - const wrapper = mount( - - ); - - wrapper.find('[data-test-subj="exceptionsPerPageBtn"] button').simulate('click'); - - expect(wrapper.find('button[data-test-subj="exceptionsPerPageItem"]').at(0).text()).toEqual( - '20 items' - ); - expect(wrapper.find('button[data-test-subj="exceptionsPerPageItem"]').at(1).text()).toEqual( - '50 items' - ); - expect(wrapper.find('button[data-test-subj="exceptionsPerPageItem"]').at(2).text()).toEqual( - '100 items' - ); - }); - - it('it invokes "onPaginationChange" when per page item is clicked', () => { - const mockOnPaginationChange = jest.fn(); - const wrapper = mount( - - ); - - wrapper.find('[data-test-subj="exceptionsPerPageBtn"] button').simulate('click'); - wrapper.find('button[data-test-subj="exceptionsPerPageItem"]').at(0).simulate('click'); - - expect(mockOnPaginationChange).toHaveBeenCalledWith({ - pagination: { pageIndex: 0, pageSize: 20, totalItemCount: 1 }, - }); - }); - - it('it renders correct total page count', () => { - const wrapper = mount( - - ); - - expect(wrapper.find('[data-test-subj="exceptionsPagination"]').at(0).prop('pageCount')).toEqual( - 4 - ); - expect( - wrapper.find('[data-test-subj="exceptionsPagination"]').at(0).prop('activePage') - ).toEqual(0); - }); - - it('it invokes "onPaginationChange" when next clicked', () => { - const mockOnPaginationChange = jest.fn(); - const wrapper = mount( - - ); - - wrapper.find('[data-test-subj="pagination-button-next"]').at(1).simulate('click'); - - expect(mockOnPaginationChange).toHaveBeenCalledWith({ - pagination: { pageIndex: 1, pageSize: 50, totalItemCount: 160 }, - }); - }); - - it('it invokes "onPaginationChange" when page clicked', () => { - const mockOnPaginationChange = jest.fn(); - const wrapper = mount( - - ); - - wrapper.find('button[data-test-subj="pagination-button-3"]').simulate('click'); - - expect(mockOnPaginationChange).toHaveBeenCalledWith({ - pagination: { pageIndex: 3, pageSize: 50, totalItemCount: 160 }, - }); - }); -}); diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_pagination.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_pagination.tsx deleted file mode 100644 index c64130e7eb56dd..00000000000000 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_pagination.tsx +++ /dev/null @@ -1,125 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { ReactElement } from 'react'; -import React, { useCallback, useState, useMemo } from 'react'; -import { - EuiContextMenuItem, - EuiButtonEmpty, - EuiPagination, - EuiFlexItem, - EuiFlexGroup, - EuiPopover, - EuiContextMenuPanel, -} from '@elastic/eui'; - -import * as i18n from '../translations'; -import type { ExceptionsPagination, Filter } from '../types'; - -interface ExceptionsViewerPaginationProps { - pagination: ExceptionsPagination; - onPaginationChange: (arg: Partial) => void; -} - -const ExceptionsViewerPaginationComponent = ({ - pagination, - onPaginationChange, -}: ExceptionsViewerPaginationProps): JSX.Element => { - const [isOpen, setIsOpen] = useState(false); - - const handleClosePerPageMenu = useCallback((): void => setIsOpen(false), [setIsOpen]); - - const handlePerPageMenuClick = useCallback( - (): void => setIsOpen((isPopoverOpen) => !isPopoverOpen), - [setIsOpen] - ); - - const handlePageClick = useCallback( - (pageIndex: number): void => { - onPaginationChange({ - pagination: { - pageIndex, - pageSize: pagination.pageSize, - totalItemCount: pagination.totalItemCount, - }, - }); - }, - [pagination, onPaginationChange] - ); - - const items = useMemo((): ReactElement[] => { - return pagination.pageSizeOptions.map((rows) => ( - { - onPaginationChange({ - pagination: { - pageIndex: 0, - pageSize: rows, - totalItemCount: pagination.totalItemCount, - }, - }); - handleClosePerPageMenu(); - }} - data-test-subj="exceptionsPerPageItem" - > - {i18n.NUMBER_OF_ITEMS(rows)} - - )); - }, [pagination, onPaginationChange, handleClosePerPageMenu]); - - const totalPages = useMemo((): number => { - if (pagination.totalItemCount > 0) { - return Math.ceil(pagination.totalItemCount / pagination.pageSize); - } else { - return 1; - } - }, [pagination]); - - return ( - - - - {i18n.ITEMS_PER_PAGE(pagination.pageSize)} - - } - isOpen={isOpen} - closePopover={handleClosePerPageMenu} - panelPaddingSize="none" - repositionOnScroll - > - - - - - - - - - ); -}; - -ExceptionsViewerPaginationComponent.displayName = 'ExceptionsViewerPaginationComponent'; - -export const ExceptionsViewerPagination = React.memo(ExceptionsViewerPaginationComponent); - -ExceptionsViewerPagination.displayName = 'ExceptionsViewerPagination'; diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_utility.test.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_utility.test.tsx deleted file mode 100644 index f600fe28f3ecb7..00000000000000 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_utility.test.tsx +++ /dev/null @@ -1,161 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { ThemeProvider } from 'styled-components'; -import { mountWithIntl } from '@kbn/test-jest-helpers'; - -import { ExceptionsViewerUtility } from './exceptions_utility'; -import { getMockTheme } from '../../../lib/kibana/kibana_react.mock'; - -const mockTheme = getMockTheme({ - eui: { - euiBreakpoints: { - l: '1200px', - }, - euiSizeM: '10px', - euiBorderThin: '1px solid #ece', - }, -}); - -describe('ExceptionsViewerUtility', () => { - it('it renders correct pluralized text when more than one exception exists', () => { - const wrapper = mountWithIntl( - - - - ); - - expect(wrapper.find('[data-test-subj="exceptionsShowing"]').at(0).text()).toEqual( - 'Showing 2 exceptions' - ); - }); - - it('it renders correct singular text when less than two exceptions exists', () => { - const wrapper = mountWithIntl( - - - - ); - - expect(wrapper.find('[data-test-subj="exceptionsShowing"]').at(0).text()).toEqual( - 'Showing 1 exception' - ); - }); - - it('it invokes "onRefreshClick" when refresh button clicked', () => { - const mockOnRefreshClick = jest.fn(); - const wrapper = mountWithIntl( - - - - ); - - wrapper.find('[data-test-subj="exceptionsRefresh"] button').simulate('click'); - - expect(mockOnRefreshClick).toHaveBeenCalledTimes(1); - }); - - it('it does not render any messages when "showEndpointList" and "showDetectionsList" are "false"', () => { - const wrapper = mountWithIntl( - - - - ); - - expect(wrapper.find('[data-test-subj="exceptionsEndpointMessage"]').exists()).toBeFalsy(); - expect(wrapper.find('[data-test-subj="exceptionsDetectionsMessage"]').exists()).toBeFalsy(); - }); - - it('it does render detections messages when "showDetectionsList" is "true"', () => { - const wrapper = mountWithIntl( - - - - ); - - expect(wrapper.find('[data-test-subj="exceptionsEndpointMessage"]').exists()).toBeFalsy(); - expect(wrapper.find('[data-test-subj="exceptionsDetectionsMessage"]').exists()).toBeTruthy(); - }); - - it('it does render endpoint messages when "showEndpointList" is "true"', () => { - const wrapper = mountWithIntl( - - - - ); - - expect(wrapper.find('[data-test-subj="exceptionsEndpointMessage"]').exists()).toBeTruthy(); - expect(wrapper.find('[data-test-subj="exceptionsDetectionsMessage"]').exists()).toBeFalsy(); - }); -}); diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_utility.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_utility.tsx deleted file mode 100644 index fd720377a1b1e3..00000000000000 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_utility.tsx +++ /dev/null @@ -1,114 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { EuiText, EuiLink, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n-react'; -import styled from 'styled-components'; - -import * as i18n from '../translations'; -import type { ExceptionsPagination } from '../types'; -import { - UtilityBar, - UtilityBarSection, - UtilityBarGroup, - UtilityBarText, - UtilityBarAction, -} from '../../utility_bar'; - -const StyledText = styled(EuiText)` - font-style: italic; -`; - -const MyUtilities = styled(EuiFlexGroup)` - height: 50px; -`; - -interface ExceptionsViewerUtilityProps { - pagination: ExceptionsPagination; - showEndpointListsOnly: boolean; - showDetectionsListsOnly: boolean; - ruleSettingsUrl: string; - onRefreshClick: () => void; -} - -const ExceptionsViewerUtilityComponent: React.FC = ({ - pagination, - showEndpointListsOnly, - showDetectionsListsOnly, - ruleSettingsUrl, - onRefreshClick, -}): JSX.Element => ( - - - - - - - {i18n.SHOWING_EXCEPTIONS(pagination.totalItemCount ?? 0)} - - - - - - {i18n.REFRESH} - - - - - - - - {showEndpointListsOnly && ( - - - - ), - }} - /> - )} - {showDetectionsListsOnly && ( - - - - ), - }} - /> - )} - - - -); - -ExceptionsViewerUtilityComponent.displayName = 'ExceptionsViewerUtilityComponent'; - -export const ExceptionsViewerUtility = React.memo(ExceptionsViewerUtilityComponent); - -ExceptionsViewerUtility.displayName = 'ExceptionsViewerUtility'; diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_header.stories.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_header.stories.tsx deleted file mode 100644 index 05cbe352fa72ed..00000000000000 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_header.stories.tsx +++ /dev/null @@ -1,69 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { storiesOf, addDecorator } from '@storybook/react'; -import { action } from '@storybook/addon-actions'; -import React from 'react'; -import { ThemeProvider } from 'styled-components'; -import { euiLightVars } from '@kbn/ui-theme'; - -import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; -import { ExceptionsViewerHeader } from './exceptions_viewer_header'; - -addDecorator((storyFn) => ( - ({ eui: euiLightVars, darkMode: false })}>{storyFn()} -)); - -storiesOf('Components/ExceptionsViewerHeader', module) - .add('loading', () => { - return ( - - ); - }) - .add('all lists', () => { - return ( - - ); - }) - .add('endpoint only', () => { - return ( - - ); - }) - .add('detections only', () => { - return ( - - ); - }); diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_header.test.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_header.test.tsx deleted file mode 100644 index d19a81e222423b..00000000000000 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_header.test.tsx +++ /dev/null @@ -1,293 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { mount } from 'enzyme'; - -import { ExceptionsViewerHeader } from './exceptions_viewer_header'; - -import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; - -describe('ExceptionsViewerHeader', () => { - it('it renders all disabled if "isInitLoading" is true', () => { - const wrapper = mount( - - ); - - expect( - wrapper.find('input[data-test-subj="exceptionsHeaderSearch"]').at(0).prop('disabled') - ).toBeTruthy(); - expect( - wrapper.find('[data-test-subj="exceptionsDetectionFilterBtn"] button').at(0).prop('disabled') - ).toBeTruthy(); - expect( - wrapper.find('[data-test-subj="exceptionsEndpointFilterBtn"] button').at(0).prop('disabled') - ).toBeTruthy(); - expect( - wrapper - .find('[data-test-subj="exceptionsHeaderAddExceptionPopoverBtn"] button') - .at(0) - .prop('disabled') - ).toBeTruthy(); - }); - - // This occurs if user does not have sufficient privileges - it('it does not display add exception button if no list types available', () => { - const wrapper = mount( - - ); - - expect(wrapper.find('[data-test-subj="exceptionsHeaderAddExceptionBtn"]').exists()).toBeFalsy(); - }); - - it('it displays toggles and add exception popover when more than one list type available', () => { - const wrapper = mount( - - ); - - expect(wrapper.find('[data-test-subj="exceptionsFilterGroupBtns"]').exists()).toBeTruthy(); - expect( - wrapper.find('[data-test-subj="exceptionsHeaderAddExceptionPopoverBtn"]').exists() - ).toBeTruthy(); - }); - - it('it does not display toggles and add exception popover if only one list type is available', () => { - const wrapper = mount( - - ); - - expect(wrapper.find('[data-test-subj="exceptionsFilterGroupBtns"]')).toHaveLength(0); - expect(wrapper.find('[data-test-subj="exceptionsHeaderAddExceptionPopoverBtn"]')).toHaveLength( - 0 - ); - }); - - it('it displays add exception button without popover if only one list type is available', () => { - const wrapper = mount( - - ); - - expect( - wrapper.find('[data-test-subj="exceptionsHeaderAddExceptionBtn"]').exists() - ).toBeTruthy(); - }); - - it('it renders detections filter toggle selected when clicked', () => { - const mockOnFilterChange = jest.fn(); - const wrapper = mount( - - ); - - wrapper.find('[data-test-subj="exceptionsDetectionFilterBtn"] button').simulate('click'); - - expect( - wrapper - .find('EuiFilterButton[data-test-subj="exceptionsDetectionFilterBtn"]') - .at(0) - .prop('hasActiveFilters') - ).toBeTruthy(); - expect( - wrapper - .find('EuiFilterButton[data-test-subj="exceptionsEndpointFilterBtn"]') - .at(0) - .prop('hasActiveFilters') - ).toBeFalsy(); - expect(mockOnFilterChange).toHaveBeenCalledWith({ - filter: { - filter: '', - tags: [], - }, - pagination: { - pageIndex: 0, - }, - showDetectionsListsOnly: true, - showEndpointListsOnly: false, - }); - }); - - it('it renders endpoint filter toggle selected and invokes "onFilterChange" when clicked', () => { - const mockOnFilterChange = jest.fn(); - const wrapper = mount( - - ); - - wrapper.find('[data-test-subj="exceptionsEndpointFilterBtn"] button').simulate('click'); - - expect( - wrapper - .find('EuiFilterButton[data-test-subj="exceptionsEndpointFilterBtn"]') - .at(0) - .prop('hasActiveFilters') - ).toBeTruthy(); - expect( - wrapper - .find('EuiFilterButton[data-test-subj="exceptionsDetectionFilterBtn"]') - .at(0) - .prop('hasActiveFilters') - ).toBeFalsy(); - expect(mockOnFilterChange).toHaveBeenCalledWith({ - filter: { - filter: '', - tags: [], - }, - pagination: { - pageIndex: 0, - }, - showDetectionsListsOnly: false, - showEndpointListsOnly: true, - }); - }); - - it('it invokes "onAddExceptionClick" when user selects to add an exception item and only endpoint exception lists are available', () => { - const mockOnAddExceptionClick = jest.fn(); - const wrapper = mount( - - ); - - wrapper.find('[data-test-subj="exceptionsHeaderAddExceptionBtn"] button').simulate('click'); - - expect(mockOnAddExceptionClick).toHaveBeenCalledTimes(1); - }); - - it('it invokes "onAddDetectionsExceptionClick" when user selects to add an exception item and only endpoint detections lists are available', () => { - const mockOnAddExceptionClick = jest.fn(); - const wrapper = mount( - - ); - - wrapper.find('[data-test-subj="exceptionsHeaderAddExceptionBtn"] button').simulate('click'); - - expect(mockOnAddExceptionClick).toHaveBeenCalledTimes(1); - }); - - it('it invokes "onAddEndpointExceptionClick" when user selects to add an exception item to endpoint list from popover', () => { - const mockOnAddExceptionClick = jest.fn(); - const wrapper = mount( - - ); - - wrapper - .find('[data-test-subj="exceptionsHeaderAddExceptionPopoverBtn"] button') - .simulate('click'); - wrapper.find('[data-test-subj="addEndpointExceptionBtn"] button').simulate('click'); - - expect(mockOnAddExceptionClick).toHaveBeenCalledTimes(1); - }); - - it('it invokes "onAddDetectionsExceptionClick" when user selects to add an exception item to endpoint list from popover', () => { - const mockOnAddExceptionClick = jest.fn(); - const wrapper = mount( - - ); - - wrapper - .find('[data-test-subj="exceptionsHeaderAddExceptionPopoverBtn"] button') - .simulate('click'); - wrapper.find('[data-test-subj="addDetectionsExceptionBtn"] button').simulate('click'); - - expect(mockOnAddExceptionClick).toHaveBeenCalledTimes(1); - }); - - it('it invokes "onFilterChange" when search used and "Enter" pressed', () => { - const mockOnFilterChange = jest.fn(); - const wrapper = mount( - - ); - - wrapper.find('EuiFieldSearch').at(0).simulate('keyup', { - charCode: 13, - code: 'Enter', - key: 'Enter', - }); - - expect(mockOnFilterChange).toHaveBeenCalled(); - }); -}); diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_header.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_header.tsx deleted file mode 100644 index dc234dc0a7ef4b..00000000000000 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_header.tsx +++ /dev/null @@ -1,209 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { EuiContextMenuPanelDescriptor } from '@elastic/eui'; -import { - EuiFieldSearch, - EuiFlexGroup, - EuiFlexItem, - EuiPopover, - EuiContextMenu, - EuiButton, - EuiFilterGroup, - EuiFilterButton, -} from '@elastic/eui'; -import React, { useEffect, useState, useCallback, useMemo } from 'react'; - -import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; -import * as i18n from '../translations'; -import type { Filter } from '../types'; - -interface ExceptionsViewerHeaderProps { - isInitLoading: boolean; - supportedListTypes: ExceptionListTypeEnum[]; - detectionsListItems: number; - endpointListItems: number; - onFilterChange: (arg: Partial) => void; - onAddExceptionClick: (type: ExceptionListTypeEnum) => void; -} - -/** - * Collection of filters and toggles for filtering exception items. - */ -const ExceptionsViewerHeaderComponent = ({ - isInitLoading, - supportedListTypes, - detectionsListItems, - endpointListItems, - onFilterChange, - onAddExceptionClick, -}: ExceptionsViewerHeaderProps): JSX.Element => { - const [filter, setFilter] = useState(''); - const [tags, setTags] = useState([]); - const [showDetectionsListsOnly, setShowDetectionsList] = useState(false); - const [showEndpointListsOnly, setShowEndpointList] = useState(false); - const [isAddExceptionMenuOpen, setAddExceptionMenuOpen] = useState(false); - - useEffect((): void => { - onFilterChange({ - filter: { filter, tags }, - pagination: { - pageIndex: 0, - }, - showDetectionsListsOnly, - showEndpointListsOnly, - }); - }, [filter, tags, showDetectionsListsOnly, showEndpointListsOnly, onFilterChange]); - - const onAddExceptionDropdownClick = useCallback( - (): void => setAddExceptionMenuOpen(!isAddExceptionMenuOpen), - [setAddExceptionMenuOpen, isAddExceptionMenuOpen] - ); - - const handleDetectionsListClick = useCallback((): void => { - setShowDetectionsList(!showDetectionsListsOnly); - setShowEndpointList(false); - }, [showDetectionsListsOnly, setShowDetectionsList, setShowEndpointList]); - - const handleEndpointListClick = useCallback((): void => { - setShowEndpointList(!showEndpointListsOnly); - setShowDetectionsList(false); - }, [showEndpointListsOnly, setShowEndpointList, setShowDetectionsList]); - - const handleOnSearch = useCallback( - (searchValue: string): void => { - const tagsRegex = /(tags:[^\s]*)/i; - const tagsMatch = searchValue.match(tagsRegex); - const foundTags: string = tagsMatch != null ? tagsMatch[0].split(':')[1] : ''; - const filterString = tagsMatch != null ? searchValue.replace(tagsRegex, '') : searchValue; - - if (foundTags.length > 0) { - setTags(foundTags.split(',')); - } - - setFilter(filterString.trim()); - }, - [setTags, setFilter] - ); - - const onAddException = useCallback( - (type: ExceptionListTypeEnum): void => { - onAddExceptionClick(type); - setAddExceptionMenuOpen(false); - }, - [onAddExceptionClick, setAddExceptionMenuOpen] - ); - - const addExceptionButtonOptions = useMemo( - (): EuiContextMenuPanelDescriptor[] => [ - { - id: 0, - items: [ - { - name: i18n.ADD_TO_ENDPOINT_LIST, - onClick: () => onAddException(ExceptionListTypeEnum.ENDPOINT), - 'data-test-subj': 'addEndpointExceptionBtn', - }, - { - name: i18n.ADD_TO_DETECTIONS_LIST, - onClick: () => onAddException(ExceptionListTypeEnum.DETECTION), - 'data-test-subj': 'addDetectionsExceptionBtn', - }, - ], - }, - ], - [onAddException] - ); - - return ( - - - - - - {supportedListTypes.length === 1 && ( - - onAddException(supportedListTypes[0])} - isDisabled={isInitLoading} - fill - > - {i18n.ADD_EXCEPTION_LABEL} - - - )} - - {supportedListTypes.length > 1 && ( - - - - - - {i18n.DETECTION_LIST} - {detectionsListItems != null ? ` (${detectionsListItems})` : ''} - - - {i18n.ENDPOINT_LIST} - {endpointListItems != null ? ` (${endpointListItems})` : ''} - - - - - - - {i18n.ADD_EXCEPTION_LABEL} - - } - isOpen={isAddExceptionMenuOpen} - closePopover={onAddExceptionDropdownClick} - anchorPosition="downCenter" - panelPaddingSize="none" - repositionOnScroll - > - - - - - - )} - - ); -}; - -ExceptionsViewerHeaderComponent.displayName = 'ExceptionsViewerHeaderComponent'; - -export const ExceptionsViewerHeader = React.memo(ExceptionsViewerHeaderComponent); - -ExceptionsViewerHeader.displayName = 'ExceptionsViewerHeader'; diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_items.test.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_items.test.tsx deleted file mode 100644 index 22c6e7dbf8ecf6..00000000000000 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_items.test.tsx +++ /dev/null @@ -1,122 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { ThemeProvider } from 'styled-components'; -import { mount } from 'enzyme'; - -import * as i18n from '../translations'; -import { getExceptionListItemSchemaMock } from '@kbn/lists-plugin/common/schemas/response/exception_list_item_schema.mock'; -import { ExceptionsViewerItems } from './exceptions_viewer_items'; -import { getMockTheme } from '../../../lib/kibana/kibana_react.mock'; -import { TestProviders } from '../../../mock'; - -const mockTheme = getMockTheme({ - eui: { - euiSize: '10px', - euiColorPrimary: '#ece', - euiColorDanger: '#ece', - }, -}); - -describe('ExceptionsViewerItems', () => { - it('it renders empty prompt if "showEmpty" is "true"', () => { - const wrapper = mount( - - - - ); - - expect(wrapper.find('[data-test-subj="exceptionsEmptyPrompt"]').exists()).toBeTruthy(); - expect(wrapper.find('[data-test-subj="exceptionsContainer"]').exists()).toBeFalsy(); - expect(wrapper.find('[data-test-subj="exceptionsEmptyPromptTitle"]').last().text()).toEqual( - i18n.EXCEPTION_EMPTY_PROMPT_TITLE - ); - expect(wrapper.find('[data-test-subj="exceptionsEmptyPromptBody"]').text()).toEqual( - i18n.EXCEPTION_EMPTY_PROMPT_BODY - ); - }); - - it('it renders no search results found prompt if "showNoResults" is "true"', () => { - const wrapper = mount( - - - - - - ); - - expect(wrapper.find('[data-test-subj="exceptionsEmptyPrompt"]').exists()).toBeTruthy(); - expect(wrapper.find('[data-test-subj="exceptionsContainer"]').exists()).toBeFalsy(); - expect(wrapper.find('[data-test-subj="exceptionsEmptyPromptTitle"]').last().text()).toEqual(''); - expect(wrapper.find('[data-test-subj="exceptionsEmptyPromptBody"]').text()).toEqual( - i18n.EXCEPTION_NO_SEARCH_RESULTS_PROMPT_BODY - ); - }); - - it('it renders exceptions if "showEmpty" and "isInitLoading" is "false", and exceptions exist', () => { - const wrapper = mount( - - - - - - ); - - expect(wrapper.find('[data-test-subj="exceptionsContainer"]').exists()).toBeTruthy(); - expect(wrapper.find('[data-test-subj="exceptionsEmptyPrompt"]').exists()).toBeFalsy(); - }); - - it('it does not render exceptions if "isInitLoading" is "true"', () => { - const wrapper = mount( - - - - - - ); - - expect(wrapper.find('[data-test-subj="exceptionsContainer"]').exists()).toBeFalsy(); - expect(wrapper.find('[data-test-subj="exceptionsEmptyPrompt"]').exists()).toBeTruthy(); - }); -}); diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_items.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_items.tsx deleted file mode 100644 index e1d91ed0a05805..00000000000000 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_items.tsx +++ /dev/null @@ -1,101 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { EuiEmptyPrompt, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import styled from 'styled-components'; - -import type { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; -import * as i18n from '../translations'; -import { ExceptionItemCard } from './exception_item_card'; -import type { ExceptionListItemIdentifiers } from '../types'; - -const MyFlexItem = styled(EuiFlexItem)` - margin: ${({ theme }) => `${theme.eui.euiSize} 0`}; - - &:first-child { - margin: ${({ theme }) => `${theme.eui.euiSizeXS} 0 ${theme.eui.euiSize}`}; - } -`; - -const MyExceptionItemContainer = styled(EuiFlexGroup)` - margin: ${({ theme }) => `0 ${theme.eui.euiSize} ${theme.eui.euiSize} 0`}; -`; - -interface ExceptionsViewerItemsProps { - showEmpty: boolean; - showNoResults: boolean; - isInitLoading: boolean; - disableActions: boolean; - exceptions: ExceptionListItemSchema[]; - loadingItemIds: ExceptionListItemIdentifiers[]; - onDeleteException: (arg: ExceptionListItemIdentifiers) => void; - onEditExceptionItem: (item: ExceptionListItemSchema) => void; -} - -const ExceptionsViewerItemsComponent: React.FC = ({ - showEmpty, - showNoResults, - isInitLoading, - exceptions, - loadingItemIds, - onDeleteException, - onEditExceptionItem, - disableActions, -}): JSX.Element => ( - - {showEmpty || showNoResults || isInitLoading ? ( - - - {showNoResults ? '' : i18n.EXCEPTION_EMPTY_PROMPT_TITLE} -

- } - body={ -

- {showNoResults - ? i18n.EXCEPTION_NO_SEARCH_RESULTS_PROMPT_BODY - : i18n.EXCEPTION_EMPTY_PROMPT_BODY} -

- } - data-test-subj="exceptionsEmptyPrompt" - /> - - ) : ( - - - {!isInitLoading && - exceptions.length > 0 && - exceptions.map((exception) => ( - - - - ))} - - - )} - -); - -ExceptionsViewerItemsComponent.displayName = 'ExceptionsViewerItemsComponent'; - -export const ExceptionsViewerItems = React.memo(ExceptionsViewerItemsComponent); - -ExceptionsViewerItems.displayName = 'ExceptionsViewerItems'; diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/index.test.tsx deleted file mode 100644 index eeab8c7e36b707..00000000000000 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/index.test.tsx +++ /dev/null @@ -1,152 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { mount } from 'enzyme'; -import { ThemeProvider } from 'styled-components'; - -import { ExceptionsViewer } from '.'; -import { useKibana } from '../../../lib/kibana'; -import { useExceptionListItems, useApi } from '@kbn/securitysolution-list-hooks'; - -import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; -import { getExceptionListSchemaMock } from '@kbn/lists-plugin/common/schemas/response/exception_list_schema.mock'; -import { getFoundExceptionListItemSchemaMock } from '@kbn/lists-plugin/common/schemas/response/found_exception_list_item_schema.mock'; -import { getMockTheme } from '../../../lib/kibana/kibana_react.mock'; - -const mockTheme = getMockTheme({ - eui: { - euiColorEmptyShade: '#ece', - euiBreakpoints: { - l: '1200px', - }, - euiSizeM: '10px', - }, -}); - -jest.mock('../../../lib/kibana'); -jest.mock('@kbn/securitysolution-list-hooks'); - -describe('ExceptionsViewer', () => { - const ruleName = 'test rule'; - - beforeEach(() => { - (useKibana as jest.Mock).mockReturnValue({ - services: { - http: {}, - application: { - getUrlForApp: () => 'some/url', - }, - }, - }); - - (useApi as jest.Mock).mockReturnValue({ - deleteExceptionItem: jest.fn().mockResolvedValue(true), - getExceptionListsItems: jest.fn().mockResolvedValue(getFoundExceptionListItemSchemaMock()), - }); - - (useExceptionListItems as jest.Mock).mockReturnValue([ - false, - [], - [], - { - page: 1, - perPage: 20, - total: 0, - }, - jest.fn(), - ]); - }); - - it('it renders loader if "loadingList" is true', () => { - (useExceptionListItems as jest.Mock).mockReturnValue([ - true, - [], - [], - { - page: 1, - perPage: 20, - total: 0, - }, - jest.fn(), - ]); - const wrapper = mount( - - - - ); - - expect(wrapper.find('[data-test-subj="loadingPanelAllRulesTable"]').exists()).toBeTruthy(); - }); - - it('it renders empty prompt if no "exceptionListMeta" passed in', () => { - const wrapper = mount( - - - - ); - - expect(wrapper.find('[data-test-subj="exceptionsEmptyPrompt"]').exists()).toBeTruthy(); - }); - - it('it renders empty prompt if no exception items exist', () => { - (useExceptionListItems as jest.Mock).mockReturnValue([ - false, - [getExceptionListSchemaMock()], - [], - { - page: 1, - perPage: 20, - total: 0, - }, - jest.fn(), - ]); - - const wrapper = mount( - - - - ); - - expect(wrapper.find('[data-test-subj="exceptionsEmptyPrompt"]').exists()).toBeTruthy(); - }); -}); diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/index.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/index.tsx deleted file mode 100644 index e724a546f8054e..00000000000000 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/index.tsx +++ /dev/null @@ -1,415 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { useCallback, useEffect, useReducer, useState } from 'react'; -import { EuiSpacer } from '@elastic/eui'; -import uuid from 'uuid'; - -import type { - ExceptionListTypeEnum, - ExceptionListItemSchema, - ExceptionListIdentifiers, - UseExceptionListItemsSuccess, -} from '@kbn/securitysolution-io-ts-list-types'; -import { useApi, useExceptionListItems } from '@kbn/securitysolution-list-hooks'; -import * as i18n from '../translations'; -import { useStateToaster } from '../../toasters'; -import { useUserData } from '../../../../detections/components/user_info'; -import { useKibana } from '../../../lib/kibana'; -import { Panel } from '../../panel'; -import { Loader } from '../../loader'; -import { ExceptionsViewerHeader } from './exceptions_viewer_header'; -import type { ExceptionListItemIdentifiers, Filter } from '../types'; -import type { State, ViewerFlyoutName } from './reducer'; -import { allExceptionItemsReducer } from './reducer'; - -import { ExceptionsViewerPagination } from './exceptions_pagination'; -import { ExceptionsViewerUtility } from './exceptions_utility'; -import { ExceptionsViewerItems } from './exceptions_viewer_items'; -import { EditExceptionFlyout } from '../edit_exception_flyout'; -import { AddExceptionFlyout } from '../add_exception_flyout'; - -const initialState: State = { - filterOptions: { filter: '', tags: [] }, - pagination: { - pageIndex: 0, - pageSize: 20, - totalItemCount: 0, - pageSizeOptions: [5, 10, 20, 50, 100, 200, 300], - }, - exceptions: [], - exceptionToEdit: null, - loadingItemIds: [], - isInitLoading: true, - currentModal: null, - exceptionListTypeToEdit: null, - totalEndpointItems: 0, - totalDetectionsItems: 0, - showEndpointListsOnly: false, - showDetectionsListsOnly: false, -}; - -interface ExceptionsViewerProps { - ruleId: string; - ruleName: string; - ruleIndices: string[]; - dataViewId?: string; - exceptionListsMeta: ExceptionListIdentifiers[]; - availableListTypes: ExceptionListTypeEnum[]; - commentsAccordionId: string; - onRuleChange?: () => void; -} - -const ExceptionsViewerComponent = ({ - ruleId, - ruleName, - ruleIndices, - dataViewId, - exceptionListsMeta, - availableListTypes, - commentsAccordionId, - onRuleChange, -}: ExceptionsViewerProps): JSX.Element => { - const { services } = useKibana(); - const [, dispatchToaster] = useStateToaster(); - const onDispatchToaster = useCallback( - ({ title, color, iconType }) => - (): void => { - dispatchToaster({ - type: 'addToaster', - toast: { - id: uuid.v4(), - title, - color, - iconType, - }, - }); - }, - [dispatchToaster] - ); - const [ - { - exceptions, - filterOptions, - pagination, - loadingItemIds, - isInitLoading, - currentModal, - exceptionToEdit, - exceptionListTypeToEdit, - totalEndpointItems, - totalDetectionsItems, - showDetectionsListsOnly, - showEndpointListsOnly, - }, - dispatch, - ] = useReducer(allExceptionItemsReducer(), { ...initialState }); - const { deleteExceptionItem, getExceptionListsItems } = useApi(services.http); - const [supportedListTypes, setSupportedListTypes] = useState([]); - - const [{ canUserCRUD, hasIndexWrite }] = useUserData(); - - useEffect((): void => { - if (!canUserCRUD || !hasIndexWrite) { - setSupportedListTypes([]); - } else { - setSupportedListTypes(availableListTypes); - } - }, [availableListTypes, canUserCRUD, hasIndexWrite]); - - const setExceptions = useCallback( - ({ - exceptions: newExceptions, - pagination: newPagination, - }: UseExceptionListItemsSuccess): void => { - dispatch({ - type: 'setExceptions', - lists: exceptionListsMeta, - exceptions: newExceptions, - pagination: newPagination, - }); - }, - [dispatch, exceptionListsMeta] - ); - const [loadingList, , , fetchListItems] = useExceptionListItems({ - http: services.http, - lists: exceptionListsMeta, - filterOptions: - filterOptions.filter !== '' || filterOptions.tags.length > 0 ? [filterOptions] : [], - pagination: { - page: pagination.pageIndex + 1, - perPage: pagination.pageSize, - total: pagination.totalItemCount, - }, - showDetectionsListsOnly, - showEndpointListsOnly, - matchFilters: true, - onSuccess: setExceptions, - onError: onDispatchToaster({ - color: 'danger', - title: i18n.FETCH_LIST_ERROR, - iconType: 'alert', - }), - }); - - const setCurrentModal = useCallback( - (modalName: ViewerFlyoutName): void => { - dispatch({ - type: 'updateModalOpen', - modalName, - }); - }, - [dispatch] - ); - - const setExceptionItemTotals = useCallback( - (endpointItemTotals: number | null, detectionItemTotals: number | null): void => { - dispatch({ - type: 'setExceptionItemTotals', - totalEndpointItems: endpointItemTotals, - totalDetectionsItems: detectionItemTotals, - }); - }, - [dispatch] - ); - - const handleGetTotals = useCallback(async (): Promise => { - await getExceptionListsItems({ - lists: exceptionListsMeta, - filterOptions: [], - pagination: { - page: 0, - perPage: 1, - total: 0, - }, - showDetectionsListsOnly: true, - showEndpointListsOnly: false, - onSuccess: ({ pagination: detectionPagination }) => { - setExceptionItemTotals(null, detectionPagination.total ?? 0); - }, - onError: () => { - const dispatchToasterError = onDispatchToaster({ - color: 'danger', - title: i18n.TOTAL_ITEMS_FETCH_ERROR, - iconType: 'alert', - }); - - dispatchToasterError(); - }, - }); - await getExceptionListsItems({ - lists: exceptionListsMeta, - filterOptions: [], - pagination: { - page: 0, - perPage: 1, - total: 0, - }, - showDetectionsListsOnly: false, - showEndpointListsOnly: true, - onSuccess: ({ pagination: endpointPagination }) => { - setExceptionItemTotals(endpointPagination.total ?? 0, null); - }, - onError: () => { - const dispatchToasterError = onDispatchToaster({ - color: 'danger', - title: i18n.TOTAL_ITEMS_FETCH_ERROR, - iconType: 'alert', - }); - - dispatchToasterError(); - }, - }); - }, [setExceptionItemTotals, exceptionListsMeta, getExceptionListsItems, onDispatchToaster]); - - const handleFetchList = useCallback((): void => { - if (fetchListItems != null) { - fetchListItems(); - handleGetTotals(); - } - }, [fetchListItems, handleGetTotals]); - - const handleFilterChange = useCallback( - (filters: Partial): void => { - dispatch({ - type: 'updateFilterOptions', - filters, - }); - }, - [dispatch] - ); - - const handleAddException = useCallback( - (type: ExceptionListTypeEnum): void => { - dispatch({ - type: 'updateExceptionListTypeToEdit', - exceptionListType: type, - }); - setCurrentModal('addException'); - }, - [setCurrentModal] - ); - - const handleEditException = useCallback( - (exception: ExceptionListItemSchema): void => { - dispatch({ - type: 'updateExceptionToEdit', - lists: exceptionListsMeta, - exception, - }); - setCurrentModal('editException'); - }, - [setCurrentModal, exceptionListsMeta] - ); - - const handleOnCancelExceptionModal = useCallback((): void => { - setCurrentModal(null); - handleFetchList(); - }, [setCurrentModal, handleFetchList]); - - const handleOnConfirmExceptionModal = useCallback((): void => { - setCurrentModal(null); - handleFetchList(); - }, [setCurrentModal, handleFetchList]); - - const setLoadingItemIds = useCallback( - (items: ExceptionListItemIdentifiers[]): void => { - dispatch({ - type: 'updateLoadingItemIds', - items, - }); - }, - [dispatch] - ); - - const handleDeleteException = useCallback( - ({ id: itemId, namespaceType }: ExceptionListItemIdentifiers) => { - setLoadingItemIds([{ id: itemId, namespaceType }]); - - deleteExceptionItem({ - id: itemId, - namespaceType, - onSuccess: () => { - setLoadingItemIds(loadingItemIds.filter(({ id }) => id !== itemId)); - handleFetchList(); - }, - onError: () => { - const dispatchToasterError = onDispatchToaster({ - color: 'danger', - title: i18n.DELETE_EXCEPTION_ERROR, - iconType: 'alert', - }); - - dispatchToasterError(); - setLoadingItemIds(loadingItemIds.filter(({ id }) => id !== itemId)); - }, - }); - }, - [setLoadingItemIds, deleteExceptionItem, loadingItemIds, handleFetchList, onDispatchToaster] - ); - - // Logic for initial render - useEffect((): void => { - if (isInitLoading && !loadingList && (exceptions.length === 0 || exceptions != null)) { - handleGetTotals(); - dispatch({ - type: 'updateIsInitLoading', - loading: false, - }); - } - }, [handleGetTotals, isInitLoading, exceptions, loadingList, dispatch]); - - // Used in utility bar info text - const ruleSettingsUrl = services.application.getUrlForApp( - `security/detections/rules/id/${encodeURI(ruleId)}/edit` - ); - - const showEmpty: boolean = !isInitLoading && !loadingList && exceptions.length === 0; - - const showNoResults: boolean = - exceptions.length === 0 && (totalEndpointItems > 0 || totalDetectionsItems > 0); - - return ( - <> - {currentModal === 'editException' && - exceptionToEdit != null && - exceptionListTypeToEdit != null && ( - - )} - - {currentModal === 'addException' && exceptionListTypeToEdit != null && ( - - )} - - - {(isInitLoading || loadingList) && ( - - )} - - - - - - - - - - - - - ); -}; - -ExceptionsViewerComponent.displayName = 'ExceptionsViewerComponent'; - -export const ExceptionsViewer = React.memo(ExceptionsViewerComponent); - -ExceptionsViewer.displayName = 'ExceptionsViewer'; diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/reducer.ts b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/reducer.ts deleted file mode 100644 index 1d91f45fd0c9f4..00000000000000 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/reducer.ts +++ /dev/null @@ -1,150 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { - ExceptionListType, - ExceptionListItemSchema, - ExceptionListIdentifiers, - Pagination, -} from '@kbn/securitysolution-io-ts-list-types'; -import type { - FilterOptions, - ExceptionsPagination, - ExceptionListItemIdentifiers, - Filter, -} from '../types'; - -export type ViewerFlyoutName = 'addException' | 'editException' | null; - -export interface State { - filterOptions: FilterOptions; - pagination: ExceptionsPagination; - exceptions: ExceptionListItemSchema[]; - exceptionToEdit: ExceptionListItemSchema | null; - loadingItemIds: ExceptionListItemIdentifiers[]; - isInitLoading: boolean; - currentModal: ViewerFlyoutName; - exceptionListTypeToEdit: ExceptionListType | null; - totalEndpointItems: number; - totalDetectionsItems: number; - showEndpointListsOnly: boolean; - showDetectionsListsOnly: boolean; -} - -export type Action = - | { - type: 'setExceptions'; - lists: ExceptionListIdentifiers[]; - exceptions: ExceptionListItemSchema[]; - pagination: Pagination; - } - | { - type: 'updateFilterOptions'; - filters: Partial; - } - | { type: 'updateIsInitLoading'; loading: boolean } - | { type: 'updateModalOpen'; modalName: ViewerFlyoutName } - | { - type: 'updateExceptionToEdit'; - lists: ExceptionListIdentifiers[]; - exception: ExceptionListItemSchema; - } - | { type: 'updateLoadingItemIds'; items: ExceptionListItemIdentifiers[] } - | { type: 'updateExceptionListTypeToEdit'; exceptionListType: ExceptionListType | null } - | { - type: 'setExceptionItemTotals'; - totalEndpointItems: number | null; - totalDetectionsItems: number | null; - }; - -export const allExceptionItemsReducer = - () => - (state: State, action: Action): State => { - switch (action.type) { - case 'setExceptions': { - const { exceptions, pagination } = action; - - return { - ...state, - pagination: { - ...state.pagination, - pageIndex: pagination.page - 1, - pageSize: pagination.perPage, - totalItemCount: pagination.total ?? 0, - }, - exceptions, - }; - } - case 'updateFilterOptions': { - const { filter, pagination, showEndpointListsOnly, showDetectionsListsOnly } = - action.filters; - return { - ...state, - filterOptions: { - ...state.filterOptions, - ...filter, - }, - pagination: { - ...state.pagination, - ...pagination, - }, - showEndpointListsOnly: showEndpointListsOnly ?? state.showEndpointListsOnly, - showDetectionsListsOnly: showDetectionsListsOnly ?? state.showDetectionsListsOnly, - }; - } - case 'setExceptionItemTotals': { - return { - ...state, - totalEndpointItems: - action.totalEndpointItems == null - ? state.totalEndpointItems - : action.totalEndpointItems, - totalDetectionsItems: - action.totalDetectionsItems == null - ? state.totalDetectionsItems - : action.totalDetectionsItems, - }; - } - case 'updateIsInitLoading': { - return { - ...state, - isInitLoading: action.loading, - }; - } - case 'updateLoadingItemIds': { - return { - ...state, - loadingItemIds: [...state.loadingItemIds, ...action.items], - }; - } - case 'updateExceptionToEdit': { - const { exception, lists } = action; - const exceptionListToEdit = lists.find((list) => { - return list !== null && exception.list_id === list.listId; - }); - return { - ...state, - exceptionToEdit: exception, - exceptionListTypeToEdit: exceptionListToEdit ? exceptionListToEdit.type : null, - }; - } - case 'updateModalOpen': { - return { - ...state, - currentModal: action.modalName, - }; - } - case 'updateExceptionListTypeToEdit': { - return { - ...state, - exceptionListTypeToEdit: action.exceptionListType, - }; - } - default: - return state; - } - }; diff --git a/x-pack/plugins/security_solution/public/common/images/illustration_product_no_results_magnifying_glass.svg b/x-pack/plugins/security_solution/public/common/images/illustration_product_no_results_magnifying_glass.svg new file mode 100644 index 00000000000000..b9a0df1630b20b --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/images/illustration_product_no_results_magnifying_glass.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/add_exception_flyout/index.test.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/add_exception_flyout/index.test.tsx similarity index 96% rename from x-pack/plugins/security_solution/public/common/components/exceptions/add_exception_flyout/index.test.tsx rename to x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/add_exception_flyout/index.test.tsx index 5945b1a0111c07..de5eca78aaffba 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/add_exception_flyout/index.test.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/add_exception_flyout/index.test.tsx @@ -14,30 +14,30 @@ import { AddExceptionFlyout } from '.'; import { getExceptionBuilderComponentLazy } from '@kbn/lists-plugin/public'; import { useAsync } from '@kbn/securitysolution-hook-utils'; import { getExceptionListSchemaMock } from '@kbn/lists-plugin/common/schemas/response/exception_list_schema.mock'; -import { useFetchIndex } from '../../../containers/source'; +import { useFetchIndex } from '../../../../common/containers/source'; import { createStubIndexPattern, stubIndexPattern } from '@kbn/data-plugin/common/stubs'; -import { useAddOrUpdateException } from '../use_add_exception'; -import { useFetchOrCreateRuleExceptionList } from '../use_fetch_or_create_rule_exception_list'; +import { useAddOrUpdateException } from '../../logic/use_add_exception'; +import { useFetchOrCreateRuleExceptionList } from '../../logic/use_fetch_or_create_rule_exception_list'; import { useSignalIndex } from '../../../../detections/containers/detection_engine/alerts/use_signal_index'; -import * as helpers from '../helpers'; +import * as helpers from '../../utils/helpers'; import { getExceptionListItemSchemaMock } from '@kbn/lists-plugin/common/schemas/response/exception_list_item_schema.mock'; import type { EntriesArray } from '@kbn/securitysolution-io-ts-list-types'; -import { TestProviders } from '../../../mock'; +import { TestProviders } from '../../../../common/mock'; import { getRulesEqlSchemaMock, getRulesSchemaMock, } from '../../../../../common/detection_engine/schemas/response/rules_schema.mocks'; import { useRuleAsync } from '../../../../detections/containers/detection_engine/rules/use_rule_async'; -import type { AlertData } from '../types'; +import type { AlertData } from '../../utils/types'; jest.mock('../../../../detections/containers/detection_engine/alerts/use_signal_index'); -jest.mock('../../../lib/kibana'); -jest.mock('../../../containers/source'); +jest.mock('../../../../common/lib/kibana'); +jest.mock('../../../../common/containers/source'); jest.mock('../../../../detections/containers/detection_engine/rules'); -jest.mock('../use_add_exception'); -jest.mock('../use_fetch_or_create_rule_exception_list'); +jest.mock('../../logic/use_add_exception'); +jest.mock('../../logic/use_fetch_or_create_rule_exception_list'); jest.mock('@kbn/securitysolution-hook-utils', () => ({ ...jest.requireActual('@kbn/securitysolution-hook-utils'), useAsync: jest.fn(), diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/add_exception_flyout/index.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/add_exception_flyout/index.tsx similarity index 96% rename from x-pack/plugins/security_solution/public/common/components/exceptions/add_exception_flyout/index.tsx rename to x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/add_exception_flyout/index.tsx index e5ae187d79d344..1a547b6e62d601 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/add_exception_flyout/index.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/add_exception_flyout/index.tsx @@ -46,17 +46,17 @@ import { isThresholdRule, } from '../../../../../common/detection_engine/utils'; import type { Status } from '../../../../../common/detection_engine/schemas/common/schemas'; -import * as i18nCommon from '../../../translations'; +import * as i18nCommon from '../../../../common/translations'; import * as i18n from './translations'; -import * as sharedI18n from '../translations'; -import { useAppToasts } from '../../../hooks/use_app_toasts'; -import { useKibana } from '../../../lib/kibana'; -import { Loader } from '../../loader'; -import { useAddOrUpdateException } from '../use_add_exception'; +import * as sharedI18n from '../../utils/translations'; +import { useAppToasts } from '../../../../common/hooks/use_app_toasts'; +import { useKibana } from '../../../../common/lib/kibana'; +import { Loader } from '../../../../common/components/loader'; +import { useAddOrUpdateException } from '../../logic/use_add_exception'; import { useSignalIndex } from '../../../../detections/containers/detection_engine/alerts/use_signal_index'; import { useRuleAsync } from '../../../../detections/containers/detection_engine/rules/use_rule_async'; -import { useFetchOrCreateRuleExceptionList } from '../use_fetch_or_create_rule_exception_list'; -import { AddExceptionComments } from '../add_exception_comments'; +import { useFetchOrCreateRuleExceptionList } from '../../logic/use_fetch_or_create_rule_exception_list'; +import { ExceptionItemComments } from '../item_comments'; import { enrichNewExceptionItemsWithComments, enrichExceptionItemsWithOS, @@ -66,11 +66,11 @@ import { entryHasNonEcsType, retrieveAlertOsTypes, filterIndexPatterns, -} from '../helpers'; +} from '../../utils/helpers'; import type { ErrorInfo } from '../error_callout'; import { ErrorCallout } from '../error_callout'; -import type { AlertData } from '../types'; -import { useFetchIndex } from '../../../containers/source'; +import type { AlertData } from '../../utils/types'; +import { useFetchIndex } from '../../../../common/containers/source'; export interface AddExceptionFlyoutProps { ruleName: string; @@ -549,7 +549,7 @@ export const AddExceptionFlyout = memo(function AddExceptionFlyout({ - diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/add_exception_flyout/translations.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/add_exception_flyout/translations.ts similarity index 100% rename from x-pack/plugins/security_solution/public/common/components/exceptions/add_exception_flyout/translations.ts rename to x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/add_exception_flyout/translations.ts diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/all_items.test.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/all_items.test.tsx new file mode 100644 index 00000000000000..0df9fad55a14d2 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/all_items.test.tsx @@ -0,0 +1,97 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { ThemeProvider } from 'styled-components'; +import { mount } from 'enzyme'; + +import { getExceptionListItemSchemaMock } from '@kbn/lists-plugin/common/schemas/response/exception_list_item_schema.mock'; +import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; + +import { ExceptionsViewerItems } from './all_items'; +import { getMockTheme } from '../../../../common/lib/kibana/kibana_react.mock'; +import { TestProviders } from '../../../../common/mock'; + +const mockTheme = getMockTheme({ + eui: { + euiSize: '10px', + euiColorPrimary: '#ece', + euiColorDanger: '#ece', + }, +}); + +describe('ExceptionsViewerItems', () => { + it('it renders empty prompt if "viewerState" is "empty"', () => { + const wrapper = mount( + + + + ); + + expect( + wrapper.find('[data-test-subj="exceptionItemViewerEmptyPrompts-empty-detection"]').exists() + ).toBeTruthy(); + expect(wrapper.find('[data-test-subj="exceptionsContainer"]').exists()).toBeFalsy(); + }); + + it('it renders no search results found prompt if "viewerState" is "empty_search"', () => { + const wrapper = mount( + + + + + + ); + + expect( + wrapper.find('[data-test-subj="exceptionItemViewerEmptyPrompts-emptySearch"]').exists() + ).toBeTruthy(); + expect(wrapper.find('[data-test-subj="exceptionsContainer"]').exists()).toBeFalsy(); + }); + + it('it renders exceptions if "viewerState" and "null"', () => { + const wrapper = mount( + + + + + + ); + + expect(wrapper.find('[data-test-subj="exceptionsContainer"]').exists()).toBeTruthy(); + }); +}); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/all_items.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/all_items.tsx new file mode 100644 index 00000000000000..fdffa134dd96f2 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/all_items.tsx @@ -0,0 +1,91 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import styled from 'styled-components'; + +import type { + ExceptionListItemSchema, + ExceptionListTypeEnum, +} from '@kbn/securitysolution-io-ts-list-types'; + +import { ExceptionItemCard } from '../exception_item_card'; +import type { ExceptionListItemIdentifiers } from '../../utils/types'; +import type { RuleReferences } from '../../logic/use_find_references'; +import type { ViewerState } from './reducer'; +import { ExeptionItemsViewerEmptyPrompts } from './empty_viewer_state'; + +const MyFlexItem = styled(EuiFlexItem)` + margin: ${({ theme }) => `${theme.eui.euiSize} 0`}; + &:first-child { + margin: ${({ theme }) => `${theme.eui.euiSizeXS} 0 ${theme.eui.euiSize}`}; + } +`; + +interface ExceptionItemsViewerProps { + isReadOnly: boolean; + disableActions: boolean; + exceptions: ExceptionListItemSchema[]; + listType: ExceptionListTypeEnum; + ruleReferences: RuleReferences | null; + viewerState: ViewerState; + onCreateExceptionListItem: () => void; + onDeleteException: (arg: ExceptionListItemIdentifiers) => void; + onEditExceptionItem: (item: ExceptionListItemSchema) => void; +} + +const ExceptionItemsViewerComponent: React.FC = ({ + isReadOnly, + exceptions, + listType, + disableActions, + ruleReferences, + viewerState, + onCreateExceptionListItem, + onDeleteException, + onEditExceptionItem, +}): JSX.Element => { + return ( + <> + {viewerState != null && viewerState !== 'deleting' ? ( + + ) : ( + + + + {exceptions.map((exception) => ( + + + + ))} + + + + )} + + ); +}; + +ExceptionItemsViewerComponent.displayName = 'ExceptionItemsViewerComponent'; + +export const ExceptionsViewerItems = React.memo(ExceptionItemsViewerComponent); + +ExceptionsViewerItems.displayName = 'ExceptionsViewerItems'; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/empty_viewer_state.test.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/empty_viewer_state.test.tsx new file mode 100644 index 00000000000000..66892e31031be2 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/empty_viewer_state.test.tsx @@ -0,0 +1,88 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { mount } from 'enzyme'; + +import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; + +import { ExeptionItemsViewerEmptyPrompts } from './empty_viewer_state'; +import * as i18n from './translations'; + +describe('ExeptionItemsViewerEmptyPrompts', () => { + it('it renders loading screen when "currentState" is "loading"', () => { + const wrapper = mount( + + ); + + expect( + wrapper.find('[data-test-subj="exceptionItemViewerEmptyPrompts-loading"]').exists() + ).toBeTruthy(); + }); + + it('it renders empty search screen when "currentState" is "empty_search"', () => { + const wrapper = mount( + + ); + + expect( + wrapper.find('[data-test-subj="exceptionItemViewerEmptyPrompts-emptySearch"]').exists() + ).toBeTruthy(); + }); + + it('it renders no endpoint items screen when "currentState" is "empty" and "listType" is "endpoint"', () => { + const wrapper = mount( + + ); + + expect(wrapper.find('[data-test-subj="exceptionsEmptyPromptBody"]').at(0).text()).toEqual( + i18n.EXCEPTION_EMPTY_ENDPOINT_PROMPT_BODY + ); + expect(wrapper.find('[data-test-subj="exceptionsEmptyPromptButton"]').at(0).text()).toEqual( + i18n.EXCEPTION_EMPTY_PROMPT_ENDPOINT_BUTTON + ); + expect( + wrapper.find('[data-test-subj="exceptionItemViewerEmptyPrompts-empty-endpoint"]').exists() + ).toBeTruthy(); + }); + + it('it renders no exception items screen when "currentState" is "empty" and "listType" is "detection"', () => { + const wrapper = mount( + + ); + + expect(wrapper.find('[data-test-subj="exceptionsEmptyPromptBody"]').at(0).text()).toEqual( + i18n.EXCEPTION_EMPTY_PROMPT_BODY + ); + expect(wrapper.find('[data-test-subj="exceptionsEmptyPromptButton"]').at(0).text()).toEqual( + i18n.EXCEPTION_EMPTY_PROMPT_BUTTON + ); + expect( + wrapper.find('[data-test-subj="exceptionItemViewerEmptyPrompts-empty-detection"]').exists() + ).toBeTruthy(); + }); +}); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/empty_viewer_state.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/empty_viewer_state.tsx new file mode 100644 index 00000000000000..2be1860f138d36 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/empty_viewer_state.tsx @@ -0,0 +1,122 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useMemo } from 'react'; +import { + EuiLoadingContent, + EuiImage, + EuiEmptyPrompt, + EuiButton, + useEuiTheme, + EuiPanel, +} from '@elastic/eui'; + +import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; +import * as i18n from './translations'; +import type { ViewerState } from './reducer'; +import illustration from '../../../../common/images/illustration_product_no_results_magnifying_glass.svg'; + +interface ExeptionItemsViewerEmptyPromptsComponentProps { + isReadOnly: boolean; + listType: ExceptionListTypeEnum; + currentState: ViewerState; + onCreateExceptionListItem: () => void; +} + +const ExeptionItemsViewerEmptyPromptsComponent = ({ + isReadOnly, + listType, + currentState, + onCreateExceptionListItem, +}: ExeptionItemsViewerEmptyPromptsComponentProps): JSX.Element => { + const { euiTheme } = useEuiTheme(); + + const content = useMemo(() => { + switch (currentState) { + case 'error': + return ( + {i18n.EXCEPTION_ERROR_TITLE}} + body={

{i18n.EXCEPTION_ERROR_DESCRIPTION}

} + data-test-subj={'exceptionItemViewerEmptyPrompts-error'} + /> + ); + case 'empty': + return ( + + {i18n.EXCEPTION_EMPTY_PROMPT_TITLE} + + } + body={ +

+ {listType === ExceptionListTypeEnum.ENDPOINT + ? i18n.EXCEPTION_EMPTY_ENDPOINT_PROMPT_BODY + : i18n.EXCEPTION_EMPTY_PROMPT_BODY} +

+ } + actions={[ + + {listType === ExceptionListTypeEnum.ENDPOINT + ? i18n.EXCEPTION_EMPTY_PROMPT_ENDPOINT_BUTTON + : i18n.EXCEPTION_EMPTY_PROMPT_BUTTON} + , + ]} + data-test-subj={`exceptionItemViewerEmptyPrompts-empty-${listType}`} + /> + ); + case 'empty_search': + return ( + } + title={

{i18n.EXCEPTION_NO_SEARCH_RESULTS_PROMPT_TITLE}

} + body={

{i18n.EXCEPTION_NO_SEARCH_RESULTS_PROMPT_BODY}

} + data-test-subj="exceptionItemViewerEmptyPrompts-emptySearch" + /> + ); + default: + return ( + + ); + } + }, [currentState, euiTheme.colors.darkestShade, isReadOnly, listType, onCreateExceptionListItem]); + + return ( + + {content} + + ); +}; + +export const ExeptionItemsViewerEmptyPrompts = React.memo(ExeptionItemsViewerEmptyPromptsComponent); + +ExeptionItemsViewerEmptyPrompts.displayName = 'ExeptionItemsViewerEmptyPrompts'; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/index.test.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/index.test.tsx new file mode 100644 index 00000000000000..d34cf07aa91461 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/index.test.tsx @@ -0,0 +1,309 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useReducer } from 'react'; +import { mount, shallow } from 'enzyme'; + +import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; + +import { ExceptionsViewer } from '.'; +import { useKibana } from '../../../../common/lib/kibana'; +import { TestProviders } from '../../../../common/mock'; +import type { Rule } from '../../../../detections/containers/detection_engine/rules/types'; +import { mockRule } from '../../../../detections/pages/detection_engine/rules/all/__mocks__/mock'; +import { useFindExceptionListReferences } from '../../logic/use_find_references'; +import * as i18n from './translations'; + +jest.mock('../../../../common/lib/kibana'); +jest.mock('@kbn/securitysolution-list-hooks'); +jest.mock('../../logic/use_find_references'); +jest.mock('react', () => { + const r = jest.requireActual('react'); + return { ...r, useReducer: jest.fn() }; +}); + +const sampleExceptionItem = { + _version: 'WzEwMjM4MSwxXQ==', + comments: [], + created_at: '2022-08-18T17:38:09.018Z', + created_by: 'elastic', + description: 'Index - exception list item', + entries: [ + { + field: 'Endpoint.policy.applied.artifacts.global.identifiers.name', + operator: 'included', + type: 'match', + value: 'sdf', + id: '6a62a5fb-a7d7-44bf-942c-a44b69baba63', + }, + ], + id: '863f3cb0-1f1c-11ed-8a48-9982ed15e50b', + item_id: '74eacd42-7617-4d32-9363-3c074a8892fe', + list_id: '9633e7f2-b92c-4a51-ad56-3e69e5e5f517', + name: 'Index - exception list item', + namespace_type: 'single', + os_types: [], + tags: [], + tie_breaker_id: '5ed24b1f-e717-4798-92ac-9eefd33bb9c0', + type: 'simple', + updated_at: '2022-08-18T17:38:09.020Z', + updated_by: 'elastic', + meta: undefined, +}; + +const getMockRule = (): Rule => ({ + ...mockRule('123'), + exceptions_list: [ + { + id: '5b543420', + list_id: 'list_id', + type: 'endpoint', + namespace_type: 'single', + }, + ], +}); + +describe('ExceptionsViewer', () => { + beforeEach(() => { + (useKibana as jest.Mock).mockReturnValue({ + services: { + http: {}, + application: { + getUrlForApp: () => 'some/url', + }, + }, + }); + + (useFindExceptionListReferences as jest.Mock).mockReturnValue([false, null]); + }); + + it('it renders loading screen when "currentState" is "loading"', () => { + (useReducer as jest.Mock).mockReturnValue([ + { + exceptions: [], + pagination: { pageIndex: 0, pageSize: 25, totalItemCount: 0, pageSizeOptions: [25, 50] }, + currenFlyout: null, + exceptionToEdit: null, + viewerState: 'loading', + exceptionLists: [], + }, + jest.fn(), + ]); + + const wrapper = mount( + + + + ); + + expect( + wrapper.find('[data-test-subj="exceptionItemViewerEmptyPrompts-loading"]').exists() + ).toBeTruthy(); + }); + + it('it renders empty search screen when "currentState" is "empty_search"', () => { + (useReducer as jest.Mock).mockReturnValue([ + { + exceptions: [], + pagination: { pageIndex: 0, pageSize: 25, totalItemCount: 0, pageSizeOptions: [25, 50] }, + currenFlyout: null, + exceptionToEdit: null, + viewerState: 'empty_search', + exceptionLists: [], + }, + jest.fn(), + ]); + + const wrapper = mount( + + + + ); + + expect( + wrapper.find('[data-test-subj="exceptionItemViewerEmptyPrompts-emptySearch"]').exists() + ).toBeTruthy(); + }); + + it('it renders no endpoint items screen when "currentState" is "empty" and "listType" is "endpoint"', () => { + (useReducer as jest.Mock).mockReturnValue([ + { + exceptions: [], + pagination: { pageIndex: 0, pageSize: 25, totalItemCount: 0, pageSizeOptions: [25, 50] }, + currenFlyout: null, + exceptionToEdit: null, + viewerState: 'empty', + exceptionLists: [], + }, + jest.fn(), + ]); + + const wrapper = mount( + + + + ); + + expect(wrapper.find('[data-test-subj="exceptionsEmptyPromptBody"]').at(0).text()).toEqual( + i18n.EXCEPTION_EMPTY_ENDPOINT_PROMPT_BODY + ); + expect(wrapper.find('[data-test-subj="exceptionsEmptyPromptButton"]').at(0).text()).toEqual( + i18n.EXCEPTION_EMPTY_PROMPT_ENDPOINT_BUTTON + ); + expect( + wrapper.find('[data-test-subj="exceptionItemViewerEmptyPrompts-empty-endpoint"]').exists() + ).toBeTruthy(); + }); + + it('it renders no exception items screen when "currentState" is "empty" and "listType" is "detection"', () => { + (useReducer as jest.Mock).mockReturnValue([ + { + exceptions: [], + pagination: { pageIndex: 0, pageSize: 25, totalItemCount: 0, pageSizeOptions: [25, 50] }, + currenFlyout: null, + exceptionToEdit: null, + viewerState: 'empty', + exceptionLists: [], + }, + jest.fn(), + ]); + + const wrapper = mount( + + + + ); + + expect(wrapper.find('[data-test-subj="exceptionsEmptyPromptBody"]').at(0).text()).toEqual( + i18n.EXCEPTION_EMPTY_PROMPT_BODY + ); + expect(wrapper.find('[data-test-subj="exceptionsEmptyPromptButton"]').at(0).text()).toEqual( + i18n.EXCEPTION_EMPTY_PROMPT_BUTTON + ); + expect( + wrapper.find('[data-test-subj="exceptionItemViewerEmptyPrompts-empty-detection"]').exists() + ).toBeTruthy(); + }); + + it('it renders add exception flyout if "currentFlyout" is "addException"', () => { + (useReducer as jest.Mock).mockReturnValue([ + { + exceptions: [], + pagination: { pageIndex: 0, pageSize: 25, totalItemCount: 0, pageSizeOptions: [25, 50] }, + currenFlyout: 'addException', + exceptionToEdit: null, + viewerState: null, + exceptionLists: [], + }, + jest.fn(), + ]); + + const wrapper = shallow( + + ); + + expect(wrapper.find('[data-test-subj="addExceptionItemFlyout"]').exists()).toBeTruthy(); + }); + + it('it renders edit exception flyout if "currentFlyout" is "editException"', () => { + (useReducer as jest.Mock).mockReturnValue([ + { + exceptions: [sampleExceptionItem], + pagination: { pageIndex: 0, pageSize: 25, totalItemCount: 0, pageSizeOptions: [25, 50] }, + currenFlyout: 'editException', + exceptionToEdit: sampleExceptionItem, + viewerState: null, + exceptionLists: [], + }, + jest.fn(), + ]); + + const wrapper = shallow( + + ); + + expect(wrapper.find('[data-test-subj="editExceptionItemFlyout"]').exists()).toBeTruthy(); + }); +}); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/index.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/index.tsx new file mode 100644 index 00000000000000..e6168bb39edbd9 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/index.tsx @@ -0,0 +1,393 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useCallback, useMemo, useEffect, useReducer, useState } from 'react'; +import { EuiPanel, EuiSpacer } from '@elastic/eui'; + +import type { + ExceptionListItemSchema, + UseExceptionListItemsSuccess, + Pagination, + ExceptionListTypeEnum, +} from '@kbn/securitysolution-io-ts-list-types'; +import { transformInput } from '@kbn/securitysolution-list-hooks'; + +import { + deleteExceptionListItemById, + fetchExceptionListsItemsByListIds, +} from '@kbn/securitysolution-list-api'; +import { DEFAULT_INDEX_PATTERN } from '../../../../../common/constants'; +import { useUserData } from '../../../../detections/components/user_info'; +import { useKibana, useToasts } from '../../../../common/lib/kibana'; +import { ExceptionsViewerSearchBar } from './search_bar'; +import type { ExceptionListItemIdentifiers } from '../../utils/types'; +import type { State, ViewerFlyoutName, ViewerState } from './reducer'; +import { allExceptionItemsReducer } from './reducer'; + +import { ExceptionsViewerPagination } from './pagination'; +import { ExceptionsViewerUtility } from './utility_bar'; +import { ExceptionsViewerItems } from './all_items'; +import { EditExceptionFlyout } from '../edit_exception_flyout'; +import { AddExceptionFlyout } from '../add_exception_flyout'; +import * as i18n from './translations'; +import { useFindExceptionListReferences } from '../../logic/use_find_references'; +import type { Rule } from '../../../../detections/containers/detection_engine/rules/types'; + +const STATES_SEARCH_HIDDEN: ViewerState[] = ['error', 'empty']; +const STATES_PAGINATION_UTILITY_HIDDEN: ViewerState[] = [ + 'loading', + 'empty_search', + 'empty', + 'error', + 'searching', +]; + +const initialState: State = { + pagination: { + pageIndex: 0, + pageSize: 25, + totalItemCount: 0, + pageSizeOptions: [1, 5, 10, 25, 50, 100, 200, 300], + }, + exceptions: [], + exceptionToEdit: null, + currenFlyout: null, + viewerState: 'loading', +}; + +export interface GetExceptionItemProps { + pagination?: Partial; + search?: string; + filters?: string; +} + +interface ExceptionsViewerProps { + rule: Rule | null; + listType: ExceptionListTypeEnum; + onRuleChange?: () => void; +} + +const ExceptionsViewerComponent = ({ + rule, + listType, + onRuleChange, +}: ExceptionsViewerProps): JSX.Element => { + const { services } = useKibana(); + const toasts = useToasts(); + const [{ canUserCRUD, hasIndexWrite }] = useUserData(); + const [isReadOnly, setReadOnly] = useState(true); + const [lastUpdated, setLastUpdated] = useState(null); + const exceptionListsToQuery = useMemo( + () => + rule != null && rule.exceptions_list != null + ? rule.exceptions_list.filter((list) => list.type === listType) + : [], + [listType, rule] + ); + + // Reducer state + const [{ exceptions, pagination, currenFlyout, exceptionToEdit, viewerState }, dispatch] = + useReducer(allExceptionItemsReducer(), { + ...initialState, + }); + + // Reducer actions + const setExceptions = useCallback( + ({ + exceptions: newExceptions, + pagination: newPagination, + }: UseExceptionListItemsSuccess): void => { + setLastUpdated(Date.now()); + + dispatch({ + type: 'setExceptions', + exceptions: newExceptions, + pagination: newPagination, + }); + }, + [dispatch] + ); + + const setViewerState = useCallback( + (state: ViewerState): void => { + dispatch({ + type: 'setViewerState', + state, + }); + }, + [dispatch] + ); + + const setFlyoutType = useCallback( + (flyoutType: ViewerFlyoutName): void => { + dispatch({ + type: 'updateFlyoutOpen', + flyoutType, + }); + }, + [dispatch] + ); + + const [_, allReferences] = useFindExceptionListReferences(exceptionListsToQuery); + + const handleFetchItems = useCallback( + async (options?: GetExceptionItemProps) => { + const abortCtrl = new AbortController(); + + const newPagination = + options?.pagination != null + ? { + page: (options.pagination.page ?? 0) + 1, + perPage: options.pagination.perPage, + } + : { + page: pagination.pageIndex + 1, + perPage: pagination.pageSize, + }; + + if (exceptionListsToQuery.length === 0) { + return { + data: [], + pageIndex: pagination.pageIndex, + itemsPerPage: pagination.pageSize, + total: 0, + }; + } + + const { + page: pageIndex, + per_page: itemsPerPage, + total, + data, + } = await fetchExceptionListsItemsByListIds({ + filter: undefined, + http: services.http, + listIds: exceptionListsToQuery.map((list) => list.list_id), + namespaceTypes: exceptionListsToQuery.map((list) => list.namespace_type), + search: options?.search, + pagination: newPagination, + signal: abortCtrl.signal, + }); + + // Please see `x-pack/plugins/lists/public/exceptions/transforms.ts` doc notes + // for context around the temporary `id` + const transformedData = data.map((item) => transformInput(item)); + + return { + data: transformedData, + pageIndex, + itemsPerPage, + total, + }; + }, + [pagination.pageIndex, pagination.pageSize, exceptionListsToQuery, services.http] + ); + + const handleGetExceptionListItems = useCallback( + async (options?: GetExceptionItemProps) => { + try { + setViewerState('loading'); + + const { pageIndex, itemsPerPage, total, data } = await handleFetchItems(options); + + setViewerState(total > 0 ? null : 'empty'); + + setExceptions({ + exceptions: data, + pagination: { + page: pageIndex, + perPage: itemsPerPage, + total, + }, + }); + } catch (e) { + setViewerState('error'); + + toasts.addError(e, { + title: i18n.EXCEPTION_ERROR_TITLE, + toastMessage: i18n.EXCEPTION_ERROR_DESCRIPTION, + }); + } + }, + [handleFetchItems, setExceptions, setViewerState, toasts] + ); + + const handleSearch = useCallback( + async (options?: GetExceptionItemProps) => { + try { + setViewerState('searching'); + + const { pageIndex, itemsPerPage, total, data } = await handleFetchItems(options); + + setViewerState(total > 0 ? null : 'empty_search'); + + setExceptions({ + exceptions: data, + pagination: { + page: pageIndex, + perPage: itemsPerPage, + total, + }, + }); + } catch (e) { + toasts.addError(e, { + title: i18n.EXCEPTION_SEARCH_ERROR_TITLE, + toastMessage: i18n.EXCEPTION_SEARCH_ERROR_BODY, + }); + } + }, + [handleFetchItems, setExceptions, setViewerState, toasts] + ); + + const handleAddException = useCallback((): void => { + setFlyoutType('addException'); + }, [setFlyoutType]); + + const handleEditException = useCallback( + (exception: ExceptionListItemSchema): void => { + dispatch({ + type: 'updateExceptionToEdit', + exception, + }); + setFlyoutType('editException'); + }, + [setFlyoutType] + ); + + const handleCancelExceptionItemFlyout = useCallback((): void => { + setFlyoutType(null); + handleGetExceptionListItems(); + }, [setFlyoutType, handleGetExceptionListItems]); + + const handleConfirmExceptionFlyout = useCallback((): void => { + setFlyoutType(null); + handleGetExceptionListItems(); + }, [setFlyoutType, handleGetExceptionListItems]); + + const handleDeleteException = useCallback( + async ({ id: itemId, name, namespaceType }: ExceptionListItemIdentifiers) => { + const abortCtrl = new AbortController(); + + try { + setViewerState('deleting'); + + await deleteExceptionListItemById({ + http: services.http, + id: itemId, + namespaceType, + signal: abortCtrl.signal, + }); + + toasts.addSuccess({ + title: i18n.EXCEPTION_ITEM_DELETE_TITLE, + text: i18n.EXCEPTION_ITEM_DELETE_TEXT(name), + }); + + await handleGetExceptionListItems(); + } catch (e) { + setViewerState('error'); + + toasts.addError(e, { + title: i18n.EXCEPTION_DELETE_ERROR_TITLE, + }); + } + }, + [handleGetExceptionListItems, services.http, setViewerState, toasts] + ); + + // User privileges checks + useEffect((): void => { + setReadOnly(!canUserCRUD || !hasIndexWrite); + }, [setReadOnly, canUserCRUD, hasIndexWrite]); + + useEffect(() => { + if (exceptionListsToQuery.length > 0) { + handleGetExceptionListItems(); + } else { + setViewerState('empty'); + } + }, [exceptionListsToQuery.length, handleGetExceptionListItems, setViewerState]); + + return ( + <> + {currenFlyout === 'editException' && exceptionToEdit != null && rule != null && ( + + )} + + {currenFlyout === 'addException' && rule != null && ( + + )} + + + <> + {!STATES_SEARCH_HIDDEN.includes(viewerState) && ( + + )} + {!STATES_PAGINATION_UTILITY_HIDDEN.includes(viewerState) && ( + <> + + + + + )} + + + + {!STATES_PAGINATION_UTILITY_HIDDEN.includes(viewerState) && ( + + )} + + + + ); +}; + +ExceptionsViewerComponent.displayName = 'ExceptionsViewerComponent'; + +export const ExceptionsViewer = React.memo(ExceptionsViewerComponent); + +ExceptionsViewer.displayName = 'ExceptionsViewer'; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/pagination.test.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/pagination.test.tsx new file mode 100644 index 00000000000000..ccca3542b25208 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/pagination.test.tsx @@ -0,0 +1,71 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { mount } from 'enzyme'; + +import { ExceptionsViewerPagination } from './pagination'; + +describe('ExceptionsViewerPagination', () => { + it('it invokes "onPaginationChange" when per page item is clicked', () => { + const mockOnPaginationChange = jest.fn(); + const wrapper = mount( + + ); + + wrapper.find('button[data-test-subj="tablePaginationPopoverButton"]').at(0).simulate('click'); + wrapper.find('button[data-test-subj="tablePagination-50-rows"]').at(0).simulate('click'); + + expect(mockOnPaginationChange).toHaveBeenCalledWith({ pagination: { page: 0, perPage: 50 } }); + }); + + it('it invokes "onPaginationChange" when next clicked', () => { + const mockOnPaginationChange = jest.fn(); + const wrapper = mount( + + ); + + wrapper.find('button[data-test-subj="pagination-button-next"]').at(0).simulate('click'); + + expect(mockOnPaginationChange).toHaveBeenCalledWith({ pagination: { page: 1, perPage: 5 } }); + }); + + it('it invokes "onPaginationChange" when page clicked', () => { + const mockOnPaginationChange = jest.fn(); + const wrapper = mount( + + ); + + wrapper.find('button[data-test-subj="pagination-button-2"]').simulate('click'); + + expect(mockOnPaginationChange).toHaveBeenCalledWith({ pagination: { page: 2, perPage: 50 } }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/pagination.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/pagination.tsx new file mode 100644 index 00000000000000..4310462164950b --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/pagination.tsx @@ -0,0 +1,66 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useCallback } from 'react'; +import { EuiTablePagination } from '@elastic/eui'; + +import type { ExceptionsPagination } from '../../utils/types'; +import * as i18n from './translations'; +import type { GetExceptionItemProps } from '.'; + +interface ExceptionsViewerPaginationProps { + pagination: ExceptionsPagination; + onPaginationChange: (arg: GetExceptionItemProps) => void; +} + +const ExceptionsViewerPaginationComponent = ({ + pagination, + onPaginationChange, +}: ExceptionsViewerPaginationProps): JSX.Element => { + const handleItemsPerPageChange = useCallback( + (pageSize: number) => { + onPaginationChange({ + pagination: { + page: pagination.pageIndex, + perPage: pageSize, + }, + }); + }, + [onPaginationChange, pagination.pageIndex] + ); + + const handlePageIndexChange = useCallback( + (pageIndex: number) => { + onPaginationChange({ + pagination: { + page: pageIndex, + perPage: pagination.pageSize, + }, + }); + }, + [onPaginationChange, pagination.pageSize] + ); + + return ( + + ); +}; + +ExceptionsViewerPaginationComponent.displayName = 'ExceptionsViewerPaginationComponent'; + +export const ExceptionsViewerPagination = React.memo(ExceptionsViewerPaginationComponent); + +ExceptionsViewerPagination.displayName = 'ExceptionsViewerPagination'; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/reducer.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/reducer.ts new file mode 100644 index 00000000000000..dbf617e55f66f2 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/reducer.ts @@ -0,0 +1,88 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { ExceptionListItemSchema, Pagination } from '@kbn/securitysolution-io-ts-list-types'; +import type { ExceptionsPagination } from '../../utils/types'; + +export type ViewerFlyoutName = 'addException' | 'editException' | null; +export type ViewerState = + | 'error' + | 'empty' + | 'empty_search' + | 'loading' + | 'searching' + | 'deleting' + | null; + +export interface State { + pagination: ExceptionsPagination; + // Individual exception items + exceptions: ExceptionListItemSchema[]; + // Exception item selected to update + exceptionToEdit: ExceptionListItemSchema | null; + // Flyout to be opened (edit vs add vs none) + currenFlyout: ViewerFlyoutName; + viewerState: ViewerState; +} + +export type Action = + | { + type: 'setExceptions'; + exceptions: ExceptionListItemSchema[]; + pagination: Pagination; + } + | { type: 'updateFlyoutOpen'; flyoutType: ViewerFlyoutName } + | { + type: 'updateExceptionToEdit'; + exception: ExceptionListItemSchema; + } + | { + type: 'setViewerState'; + state: ViewerState; + }; + +export const allExceptionItemsReducer = + () => + (state: State, action: Action): State => { + switch (action.type) { + case 'setExceptions': { + const { exceptions, pagination } = action; + + return { + ...state, + pagination: { + ...state.pagination, + pageIndex: pagination.page - 1, + pageSize: pagination.perPage, + totalItemCount: pagination.total ?? 0, + }, + exceptions, + }; + } + case 'updateExceptionToEdit': { + const { exception } = action; + return { + ...state, + exceptionToEdit: exception, + }; + } + case 'updateFlyoutOpen': { + return { + ...state, + currenFlyout: action.flyoutType, + }; + } + case 'setViewerState': { + return { + ...state, + viewerState: action.state, + }; + } + default: + return state; + } + }; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/search_bar.test.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/search_bar.test.tsx new file mode 100644 index 00000000000000..454036b3f30360 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/search_bar.test.tsx @@ -0,0 +1,69 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { mount } from 'enzyme'; + +import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; + +import { ExceptionsViewerSearchBar } from './search_bar'; + +describe('ExceptionsViewerSearchBar', () => { + it('it does not display add exception button if user is read only', () => { + const wrapper = mount( + + ); + + expect(wrapper.find('[data-test-subj="exceptionsHeaderAddExceptionBtn"]').exists()).toBeFalsy(); + }); + + it('it invokes "onAddExceptionClick" when user selects to add an exception item', () => { + const mockOnAddExceptionClick = jest.fn(); + const wrapper = mount( + + ); + + wrapper.find('[data-test-subj="exceptionsHeaderAddExceptionBtn"] button').simulate('click'); + + expect(wrapper.find('[data-test-subj="exceptionsHeaderAddExceptionBtn"]').at(0).text()).toEqual( + 'Add rule exception' + ); + expect(mockOnAddExceptionClick).toHaveBeenCalledWith('detection'); + }); + + it('it invokes "onAddExceptionClick" when user selects to add an endpoint exception item', () => { + const mockOnAddExceptionClick = jest.fn(); + const wrapper = mount( + + ); + + wrapper.find('[data-test-subj="exceptionsHeaderAddExceptionBtn"] button').simulate('click'); + + expect(wrapper.find('[data-test-subj="exceptionsHeaderAddExceptionBtn"]').at(0).text()).toEqual( + 'Add endpoint exception' + ); + expect(mockOnAddExceptionClick).toHaveBeenCalledWith('endpoint'); + }); +}); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/search_bar.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/search_bar.tsx new file mode 100644 index 00000000000000..1cc371c440dba1 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/search_bar.tsx @@ -0,0 +1,116 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useCallback, useMemo } from 'react'; +import { EuiFlexGroup, EuiFlexItem, EuiButton, EuiSearchBar } from '@elastic/eui'; + +import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; +import * as i18n from '../../utils/translations'; +import type { GetExceptionItemProps } from '.'; + +const ITEMS_SCHEMA = { + strict: true, + fields: { + created_by: { + type: 'string', + }, + description: { + type: 'string', + }, + id: { + type: 'string', + }, + item_id: { + type: 'string', + }, + list_id: { + type: 'string', + }, + name: { + type: 'string', + }, + os_types: { + type: 'string', + }, + tags: { + type: 'string', + }, + }, +}; + +interface ExceptionsViewerSearchBarProps { + canAddException: boolean; + // Exception list type used to determine what type of item is + // being created when "onAddExceptionClick" is invoked + listType: ExceptionListTypeEnum; + isSearching: boolean; + onSearch: (arg: GetExceptionItemProps) => void; + onAddExceptionClick: (type: ExceptionListTypeEnum) => void; +} + +/** + * Search exception items and take actions (to creat an item) + */ +const ExceptionsViewerSearchBarComponent = ({ + canAddException, + listType, + isSearching, + onSearch, + onAddExceptionClick, +}: ExceptionsViewerSearchBarProps): JSX.Element => { + const handleOnSearch = useCallback( + ({ queryText }): void => { + onSearch({ search: queryText }); + }, + [onSearch] + ); + + const handleAddException = useCallback(() => { + onAddExceptionClick(listType); + }, [onAddExceptionClick, listType]); + + const addExceptionButtonText = useMemo(() => { + return listType === ExceptionListTypeEnum.ENDPOINT + ? i18n.ADD_TO_ENDPOINT_LIST + : i18n.ADD_TO_DETECTIONS_LIST; + }, [listType]); + + return ( + + + + + {!canAddException && ( + + + {addExceptionButtonText} + + + )} + + ); +}; + +ExceptionsViewerSearchBarComponent.displayName = 'ExceptionsViewerSearchBarComponent'; + +export const ExceptionsViewerSearchBar = React.memo(ExceptionsViewerSearchBarComponent); + +ExceptionsViewerSearchBar.displayName = 'ExceptionsViewerSearchBar'; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/translations.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/translations.ts new file mode 100644 index 00000000000000..727fb78bede2aa --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/translations.ts @@ -0,0 +1,114 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; + +export const EXCEPTION_NO_SEARCH_RESULTS_PROMPT_TITLE = i18n.translate( + 'xpack.securitySolution.exceptions.allItems.noSearchResultsPromptTitle', + { + defaultMessage: 'No results match your search criteria', + } +); + +export const EXCEPTION_NO_SEARCH_RESULTS_PROMPT_BODY = i18n.translate( + 'xpack.securitySolution.exceptions.allItems.noSearchResultsPromptBody', + { + defaultMessage: 'Try modifying your search.', + } +); + +export const EXCEPTION_EMPTY_PROMPT_TITLE = i18n.translate( + 'xpack.securitySolution.exceptions.allItems.addExceptionsEmptyPromptTitle', + { + defaultMessage: 'Add exceptions to this rule', + } +); + +export const EXCEPTION_EMPTY_PROMPT_BODY = i18n.translate( + 'xpack.securitySolution.exceptions.allItems.emptyPromptBody', + { + defaultMessage: 'There are no exceptions for this rule. Create your first rule exception.', + } +); + +export const EXCEPTION_EMPTY_ENDPOINT_PROMPT_BODY = i18n.translate( + 'xpack.securitySolution.exceptions.allItems.endpoint.emptyPromptBody', + { + defaultMessage: + 'There are no endpoint exceptions. Endpoint exceptions are applied to the endpoint and the detection rule. Create your first endpoint exception.', + } +); + +export const EXCEPTION_EMPTY_PROMPT_BUTTON = i18n.translate( + 'xpack.securitySolution.exceptions.allItems.emptyPromptButtonLabel', + { + defaultMessage: 'Add rule exception', + } +); + +export const EXCEPTION_EMPTY_PROMPT_ENDPOINT_BUTTON = i18n.translate( + 'xpack.securitySolution.exceptions.allItems.endpoint.emptyPromptButtonLabel', + { + defaultMessage: 'Add endpoint exception', + } +); + +export const EXCEPTION_ERROR_TITLE = i18n.translate( + 'xpack.securitySolution.exceptions.allItems.exceptionItemsFetchError', + { + defaultMessage: 'Unable to load exception items', + } +); + +export const EXCEPTION_ERROR_DESCRIPTION = i18n.translate( + 'xpack.securitySolution.exceptions.allItems.exceptionItemsFetchErrorDescription', + { + defaultMessage: + 'There was an error loading the exception items. Contact your administrator for help.', + } +); + +export const EXCEPTION_SEARCH_ERROR_TITLE = i18n.translate( + 'xpack.securitySolution.exceptions.allItems.exceptionItemSearchErrorTitle', + { + defaultMessage: 'Error searching', + } +); + +export const EXCEPTION_SEARCH_ERROR_BODY = i18n.translate( + 'xpack.securitySolution.exceptions.allItems.exceptionItemSearchErrorBody', + { + defaultMessage: 'An error occurred searching for exception items. Please try again.', + } +); + +export const EXCEPTION_DELETE_ERROR_TITLE = i18n.translate( + 'xpack.securitySolution.exceptions.allItems.exceptionDeleteErrorTitle', + { + defaultMessage: 'Error deleting exception item', + } +); + +export const EXCEPTION_ITEMS_PAGINATION_ARIA_LABEL = i18n.translate( + 'xpack.securitySolution.exceptions.allItems.paginationAriaLabel', + { + defaultMessage: 'Exception item table pagination', + } +); + +export const EXCEPTION_ITEM_DELETE_TITLE = i18n.translate( + 'xpack.securitySolution.exceptions.allItems.exceptionItemDeleteSuccessTitle', + { + defaultMessage: 'Exception deleted', + } +); + +export const EXCEPTION_ITEM_DELETE_TEXT = (itemName: string) => + i18n.translate('xpack.securitySolution.exceptions.allItems.exceptionItemDeleteSuccessText', { + values: { itemName }, + defaultMessage: '"{itemName}" deleted successfully.', + }); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/utility_bar.test.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/utility_bar.test.tsx new file mode 100644 index 00000000000000..aa604dbfbf0014 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/utility_bar.test.tsx @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { mountWithIntl } from '@kbn/test-jest-helpers'; + +import { ExceptionsViewerUtility } from './utility_bar'; +import { TestProviders } from '../../../../common/mock'; + +describe('ExceptionsViewerUtility', () => { + it('it renders correct item counts', () => { + const wrapper = mountWithIntl( + + + + ); + + expect(wrapper.find('[data-test-subj="exceptionsShowing"]').at(0).text()).toEqual( + 'Showing 1-50 of 105' + ); + }); + + it('it renders last updated message', () => { + const wrapper = mountWithIntl( + + + + ); + + expect(wrapper.find('[data-test-subj="exceptionsViewerLastUpdated"]').at(0).text()).toEqual( + 'Updated now' + ); + }); +}); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/utility_bar.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/utility_bar.tsx new file mode 100644 index 00000000000000..a68930a9a40b86 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/all_exception_items_table/utility_bar.tsx @@ -0,0 +1,97 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { EuiText, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import styled from 'styled-components'; + +import { FormattedMessage } from '@kbn/i18n-react'; +import type { ExceptionsPagination } from '../../utils/types'; +import { + UtilityBar, + UtilityBarSection, + UtilityBarGroup, + UtilityBarText, +} from '../../../../common/components/utility_bar'; +import { FormattedRelativePreferenceDate } from '../../../../common/components/formatted_date'; + +const StyledText = styled.span` + font-weight: bold; +`; + +const MyUtilities = styled(EuiFlexGroup)` + height: 50px; +`; + +const StyledCondition = styled.span` + display: inline-block !important; + vertical-align: middle !important; +`; + +interface ExceptionsViewerUtilityProps { + pagination: ExceptionsPagination; + // Corresponds to last time exception items were fetched + lastUpdated: string | number | null; +} + +/** + * Utilities include exception item counts and group by options + */ +const ExceptionsViewerUtilityComponent: React.FC = ({ + pagination, + lastUpdated, +}): JSX.Element => ( + + + + + + + {`1-${Math.min( + pagination.pageSize, + pagination.totalItemCount + )}`} + ), + partTwo: {`${pagination.totalItemCount}`}, + }} + /> + + + + + + + + + + + ), + }} + /> + + + +); + +ExceptionsViewerUtilityComponent.displayName = 'ExceptionsViewerUtilityComponent'; + +export const ExceptionsViewerUtility = React.memo(ExceptionsViewerUtilityComponent); + +ExceptionsViewerUtility.displayName = 'ExceptionsViewerUtility'; diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/edit_exception_flyout/index.test.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/edit_exception_flyout/index.test.tsx similarity index 96% rename from x-pack/plugins/security_solution/public/common/components/exceptions/edit_exception_flyout/index.test.tsx rename to x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/edit_exception_flyout/index.test.tsx index 2885920222b5d7..d5d5c3fc373169 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/edit_exception_flyout/index.test.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/edit_exception_flyout/index.test.tsx @@ -12,10 +12,10 @@ import type { ReactWrapper } from 'enzyme'; import { mount } from 'enzyme'; import { EditExceptionFlyout } from '.'; -import { useCurrentUser } from '../../../lib/kibana'; -import { useFetchIndex } from '../../../containers/source'; +import { useCurrentUser } from '../../../../common/lib/kibana'; +import { useFetchIndex } from '../../../../common/containers/source'; import { stubIndexPattern, createStubIndexPattern } from '@kbn/data-plugin/common/stubs'; -import { useAddOrUpdateException } from '../use_add_exception'; +import { useAddOrUpdateException } from '../../logic/use_add_exception'; import { useSignalIndex } from '../../../../detections/containers/detection_engine/alerts/use_signal_index'; import { getExceptionListItemSchemaMock } from '@kbn/lists-plugin/common/schemas/response/exception_list_item_schema.mock'; import type { EntriesArray } from '@kbn/securitysolution-io-ts-list-types'; @@ -24,7 +24,7 @@ import { getRulesSchemaMock, } from '../../../../../common/detection_engine/schemas/response/rules_schema.mocks'; import { useRuleAsync } from '../../../../detections/containers/detection_engine/rules/use_rule_async'; -import { getMockTheme } from '../../../lib/kibana/kibana_react.mock'; +import { getMockTheme } from '../../../../common/lib/kibana/kibana_react.mock'; import { getExceptionBuilderComponentLazy } from '@kbn/lists-plugin/public'; const mockTheme = getMockTheme({ @@ -36,11 +36,11 @@ const mockTheme = getMockTheme({ }, }); -jest.mock('../../../lib/kibana'); +jest.mock('../../../../common/lib/kibana'); jest.mock('../../../../detections/containers/detection_engine/rules'); -jest.mock('../use_add_exception'); -jest.mock('../../../containers/source'); -jest.mock('../use_fetch_or_create_rule_exception_list'); +jest.mock('../../logic/use_add_exception'); +jest.mock('../../../../common/containers/source'); +jest.mock('../../logic/use_fetch_or_create_rule_exception_list'); jest.mock('../../../../detections/containers/detection_engine/alerts/use_signal_index'); jest.mock('../../../../detections/containers/detection_engine/rules/use_rule_async'); jest.mock('@kbn/lists-plugin/public'); diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/edit_exception_flyout/index.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/edit_exception_flyout/index.tsx similarity index 96% rename from x-pack/plugins/security_solution/public/common/components/exceptions/edit_exception_flyout/index.tsx rename to x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/edit_exception_flyout/index.tsx index 73095d11decaff..78e86dd4f1fa05 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/edit_exception_flyout/index.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/edit_exception_flyout/index.tsx @@ -45,16 +45,16 @@ import { isNewTermsRule, isThresholdRule, } from '../../../../../common/detection_engine/utils'; -import { useFetchIndex } from '../../../containers/source'; +import { useFetchIndex } from '../../../../common/containers/source'; import { useSignalIndex } from '../../../../detections/containers/detection_engine/alerts/use_signal_index'; import { useRuleAsync } from '../../../../detections/containers/detection_engine/rules/use_rule_async'; import * as i18n from './translations'; -import * as sharedI18n from '../translations'; -import { useKibana } from '../../../lib/kibana'; -import { useAppToasts } from '../../../hooks/use_app_toasts'; -import { useAddOrUpdateException } from '../use_add_exception'; -import { AddExceptionComments } from '../add_exception_comments'; +import * as sharedI18n from '../../utils/translations'; +import { useKibana } from '../../../../common/lib/kibana'; +import { useAppToasts } from '../../../../common/hooks/use_app_toasts'; +import { useAddOrUpdateException } from '../../logic/use_add_exception'; +import { ExceptionItemComments } from '../item_comments'; import { enrichExistingExceptionItemWithComments, enrichExceptionItemsWithOS, @@ -62,8 +62,8 @@ import { entryHasNonEcsType, lowercaseHashValues, filterIndexPatterns, -} from '../helpers'; -import { Loader } from '../../loader'; +} from '../../utils/helpers'; +import { Loader } from '../../../../common/components/loader'; import type { ErrorInfo } from '../error_callout'; import { ErrorCallout } from '../error_callout'; @@ -410,7 +410,7 @@ export const EditExceptionFlyout = memo(function EditExceptionFlyout({ - (({ comments }) => { + const { euiTheme } = useEuiTheme(); + + return ( + + + {i18n.exceptionItemCommentsAccordion(comments.length)} +
+ } + arrowDisplay="none" + data-test-subj="exceptionsViewerCommentAccordion" + > + + + + + + ); +}); + +ExceptionItemCardComments.displayName = 'ExceptionItemCardComments'; diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item_card/exception_item_card_conditions.test.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/exception_item_card/conditions.test.tsx similarity index 98% rename from x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item_card/exception_item_card_conditions.test.tsx rename to x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/exception_item_card/conditions.test.tsx index e31f049e55e13d..33fbb2150323c8 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item_card/exception_item_card_conditions.test.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/exception_item_card/conditions.test.tsx @@ -8,8 +8,8 @@ import React from 'react'; import { mount } from 'enzyme'; -import { TestProviders } from '../../../../mock'; -import { ExceptionItemCardConditions } from './exception_item_card_conditions'; +import { TestProviders } from '../../../../common/mock'; +import { ExceptionItemCardConditions } from './conditions'; describe('ExceptionItemCardConditions', () => { it('it includes os condition if one exists', () => { diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item_card/exception_item_card_conditions.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/exception_item_card/conditions.tsx similarity index 94% rename from x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item_card/exception_item_card_conditions.tsx rename to x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/exception_item_card/conditions.tsx index 451cb3a4ecf313..95e3f7c2118887 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item_card/exception_item_card_conditions.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/exception_item_card/conditions.tsx @@ -6,7 +6,14 @@ */ import React, { memo, useMemo, useCallback } from 'react'; -import { EuiExpression, EuiToken, EuiFlexGroup, EuiFlexItem, EuiBadge } from '@elastic/eui'; +import { + EuiExpression, + EuiToken, + EuiFlexGroup, + EuiFlexItem, + EuiBadge, + EuiPanel, +} from '@elastic/eui'; import styled from 'styled-components'; import type { EntryExists, @@ -21,7 +28,7 @@ import type { import { ListOperatorTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; import * as i18n from './translations'; -import { ValueWithSpaceWarning } from '../value_with_space_warning/value_with_space_warning'; +import { ValueWithSpaceWarning } from '../value_with_space_warning'; const OS_LABELS = Object.freeze({ linux: i18n.OS_LINUX, @@ -60,6 +67,12 @@ const StyledCondition = styled('span')` margin-right: 6px; `; +const StyledConditionContent = styled(EuiPanel)` + border: 1px; + border-color: #d3dae6; + border-style: solid; +`; + export interface CriteriaConditionsProps { entries: ExceptionListItemSchema['entries']; dataTestSubj: string; @@ -148,7 +161,12 @@ export const ExceptionItemCardConditions = memo( ); return ( -
+ {osLabel != null && (
@@ -183,7 +201,7 @@ export const ExceptionItemCardConditions = memo(
); })} -
+ ); } ); diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item_card/exception_item_card_header.test.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/exception_item_card/header.test.tsx similarity index 96% rename from x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item_card/exception_item_card_header.test.tsx rename to x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/exception_item_card/header.test.tsx index fe8811152e2e16..2a60e813757455 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item_card/exception_item_card_header.test.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/exception_item_card/header.test.tsx @@ -11,8 +11,8 @@ import { getExceptionListItemSchemaMock } from '@kbn/lists-plugin/common/schemas import { ThemeProvider } from 'styled-components'; import * as i18n from './translations'; -import { ExceptionItemCardHeader } from './exception_item_card_header'; -import { getMockTheme } from '../../../../lib/kibana/kibana_react.mock'; +import { ExceptionItemCardHeader } from './header'; +import { getMockTheme } from '../../../../common/lib/kibana/kibana_react.mock'; const mockTheme = getMockTheme({ eui: { diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item_card/exception_item_card_header.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/exception_item_card/header.tsx similarity index 100% rename from x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item_card/exception_item_card_header.tsx rename to x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/exception_item_card/header.tsx diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item_card/index.test.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/exception_item_card/index.test.tsx similarity index 52% rename from x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item_card/index.test.tsx rename to x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/exception_item_card/index.test.tsx index 46a0f74642c082..5219f5d72d8470 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item_card/index.test.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/exception_item_card/index.test.tsx @@ -6,40 +6,52 @@ */ import React from 'react'; -import { ThemeProvider } from 'styled-components'; import { mount } from 'enzyme'; import { ExceptionItemCard } from '.'; import { getExceptionListItemSchemaMock } from '@kbn/lists-plugin/common/schemas/response/exception_list_item_schema.mock'; import { getCommentsArrayMock } from '@kbn/lists-plugin/common/schemas/types/comment.mock'; -import { getMockTheme } from '../../../../lib/kibana/kibana_react.mock'; +import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; +import { TestProviders } from '../../../../common/mock'; -jest.mock('../../../../lib/kibana'); - -const mockTheme = getMockTheme({ - eui: { - euiColorDanger: '#ece', - euiColorLightestShade: '#ece', - euiColorPrimary: '#ece', - euiFontWeightSemiBold: 1, - }, -}); +jest.mock('../../../../common/lib/kibana'); describe('ExceptionItemCard', () => { it('it renders header, item meta information and conditions', () => { const exceptionItem = { ...getExceptionListItemSchemaMock(), comments: [] }; const wrapper = mount( - + - + ); expect(wrapper.find('ExceptionItemCardHeader')).toHaveLength(1); @@ -54,16 +66,37 @@ describe('ExceptionItemCard', () => { const exceptionItem = { ...getExceptionListItemSchemaMock(), comments: getCommentsArrayMock() }; const wrapper = mount( - + - + ); expect(wrapper.find('ExceptionItemCardHeader')).toHaveLength(1); @@ -78,16 +111,37 @@ describe('ExceptionItemCard', () => { const exceptionItem = getExceptionListItemSchemaMock(); const wrapper = mount( - + - + ); expect(wrapper.find('button[data-test-subj="item-actionButton"]').exists()).toBeFalsy(); @@ -98,16 +152,37 @@ describe('ExceptionItemCard', () => { const exceptionItem = getExceptionListItemSchemaMock(); const wrapper = mount( - + - + ); // click on popover @@ -127,16 +202,37 @@ describe('ExceptionItemCard', () => { const exceptionItem = getExceptionListItemSchemaMock(); const wrapper = mount( - + - + ); // click on popover @@ -150,6 +246,7 @@ describe('ExceptionItemCard', () => { expect(mockOnDeleteException).toHaveBeenCalledWith({ id: '1', + name: 'some name', namespaceType: 'single', }); }); @@ -158,16 +255,37 @@ describe('ExceptionItemCard', () => { const exceptionItem = getExceptionListItemSchemaMock(); exceptionItem.comments = getCommentsArrayMock(); const wrapper = mount( - + - + ); expect(wrapper.find('.euiAccordion-isOpen')).toHaveLength(0); diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item_card/index.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/exception_item_card/index.tsx similarity index 60% rename from x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item_card/index.tsx rename to x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/exception_item_card/index.tsx index 322050e27e4b8a..cae3136dc6ad4f 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item_card/index.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/exception_item_card/index.tsx @@ -6,50 +6,46 @@ */ import type { EuiCommentProps } from '@elastic/eui'; -import { - EuiPanel, - EuiFlexGroup, - EuiCommentList, - EuiAccordion, - EuiFlexItem, - EuiText, - useEuiTheme, -} from '@elastic/eui'; +import { EuiPanel, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import React, { useMemo, useCallback } from 'react'; import type { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; +import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; -import { getFormattedComments } from '../../helpers'; -import type { ExceptionListItemIdentifiers } from '../../types'; +import { getFormattedComments } from '../../utils/helpers'; +import type { ExceptionListItemIdentifiers } from '../../utils/types'; import * as i18n from './translations'; -import { ExceptionItemCardHeader } from './exception_item_card_header'; -import { ExceptionItemCardConditions } from './exception_item_card_conditions'; -import { ExceptionItemCardMetaInfo } from './exception_item_card_meta'; +import { ExceptionItemCardHeader } from './header'; +import { ExceptionItemCardConditions } from './conditions'; +import { ExceptionItemCardMetaInfo } from './meta'; +import type { RuleReferenceSchema } from '../../../../../common/detection_engine/schemas/response'; +import { ExceptionItemCardComments } from './comments'; export interface ExceptionItemProps { - loadingItemIds: ExceptionListItemIdentifiers[]; exceptionItem: ExceptionListItemSchema; + listType: ExceptionListTypeEnum; + disableActions: boolean; + ruleReferences: RuleReferenceSchema[]; onDeleteException: (arg: ExceptionListItemIdentifiers) => void; onEditException: (item: ExceptionListItemSchema) => void; - disableActions: boolean; dataTestSubj: string; } const ExceptionItemCardComponent = ({ disableActions, - loadingItemIds, exceptionItem, + listType, + ruleReferences, onDeleteException, onEditException, dataTestSubj, }: ExceptionItemProps): JSX.Element => { - const { euiTheme } = useEuiTheme(); - const handleDelete = useCallback((): void => { onDeleteException({ id: exceptionItem.id, + name: exceptionItem.name, namespaceType: exceptionItem.namespace_type, }); - }, [onDeleteException, exceptionItem.id, exceptionItem.namespace_type]); + }, [onDeleteException, exceptionItem.id, exceptionItem.name, exceptionItem.namespace_type]); const handleEdit = useCallback((): void => { onEditException(exceptionItem); @@ -59,11 +55,6 @@ const ExceptionItemCardComponent = ({ return getFormattedComments(exceptionItem.comments); }, [exceptionItem.comments]); - const disableItemActions = useMemo((): boolean => { - const foundItems = loadingItemIds.some(({ id }) => id === exceptionItem.id); - return disableActions || foundItems; - }, [loadingItemIds, exceptionItem.id, disableActions]); - return ( @@ -73,24 +64,31 @@ const ExceptionItemCardComponent = ({ actions={[ { key: 'edit', - icon: 'pencil', - label: i18n.EXCEPTION_ITEM_EDIT_BUTTON, + icon: 'controlsHorizontal', + label: + listType === ExceptionListTypeEnum.ENDPOINT + ? i18n.ENDPOINT_EXCEPTION_ITEM_EDIT_BUTTON + : i18n.EXCEPTION_ITEM_EDIT_BUTTON, onClick: handleEdit, }, { key: 'delete', icon: 'trash', - label: i18n.EXCEPTION_ITEM_DELETE_BUTTON, + label: + listType === ExceptionListTypeEnum.ENDPOINT + ? i18n.ENDPOINT_EXCEPTION_ITEM_DELETE_BUTTON + : i18n.EXCEPTION_ITEM_DELETE_BUTTON, onClick: handleDelete, }, ]} - disableActions={disableItemActions} + disableActions={disableActions} dataTestSubj="exceptionItemCardHeader" /> @@ -101,24 +99,7 @@ const ExceptionItemCardComponent = ({ dataTestSubj="exceptionItemCardConditions" /> - {formattedComments.length > 0 && ( - - - {i18n.exceptionItemCommentsAccordion(formattedComments.length)} - - } - arrowDisplay="none" - data-test-subj="exceptionsViewerCommentAccordion" - > - - - - - - )} + {formattedComments.length > 0 && } ); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/exception_item_card/meta.test.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/exception_item_card/meta.test.tsx new file mode 100644 index 00000000000000..c755321f5f4eaf --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/exception_item_card/meta.test.tsx @@ -0,0 +1,184 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { mount } from 'enzyme'; +import { getExceptionListItemSchemaMock } from '@kbn/lists-plugin/common/schemas/response/exception_list_item_schema.mock'; + +import { ExceptionItemCardMetaInfo } from './meta'; +import { TestProviders } from '../../../../common/mock'; + +describe('ExceptionItemCardMetaInfo', () => { + it('it renders item creation info', () => { + const wrapper = mount( + + + + ); + + expect( + wrapper.find('[data-test-subj="exceptionItemMeta-createdBy-value1"]').at(0).text() + ).toEqual('Apr 20, 2020 @ 15:25:31.830'); + expect( + wrapper.find('[data-test-subj="exceptionItemMeta-createdBy-value2"]').at(0).text() + ).toEqual('some user'); + }); + + it('it renders item update info', () => { + const wrapper = mount( + + + + ); + + expect( + wrapper.find('[data-test-subj="exceptionItemMeta-updatedBy-value1"]').at(0).text() + ).toEqual('Apr 20, 2020 @ 15:25:31.830'); + expect( + wrapper.find('[data-test-subj="exceptionItemMeta-updatedBy-value2"]').at(0).text() + ).toEqual('some user'); + }); + + it('it renders references info', () => { + const wrapper = mount( + + + + ); + + expect( + wrapper.find('[data-test-subj="exceptionItemMeta-affectedRulesButton"]').at(0).text() + ).toEqual('Affects 1 rule'); + }); + + it('it renders references info when multiple references exist', () => { + const wrapper = mount( + + + + ); + + expect( + wrapper.find('[data-test-subj="exceptionItemMeta-affectedRulesButton"]').at(0).text() + ).toEqual('Affects 2 rules'); + }); +}); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/exception_item_card/meta.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/exception_item_card/meta.tsx new file mode 100644 index 00000000000000..a24526dd04e3a5 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/exception_item_card/meta.tsx @@ -0,0 +1,161 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { memo, useMemo, useState } from 'react'; +import type { EuiContextMenuPanelProps } from '@elastic/eui'; +import { + EuiBadge, + EuiContextMenuItem, + EuiContextMenuPanel, + EuiFlexGroup, + EuiFlexItem, + EuiToolTip, + EuiText, + EuiButtonEmpty, + EuiPopover, +} from '@elastic/eui'; +import type { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; +import styled from 'styled-components'; + +import * as i18n from './translations'; +import { FormattedDate } from '../../../../common/components/formatted_date'; +import { SecurityPageName } from '../../../../../common/constants'; +import type { RuleReferenceSchema } from '../../../../../common/detection_engine/schemas/response'; +import { SecuritySolutionLinkAnchor } from '../../../../common/components/links'; +import { RuleDetailTabs } from '../../../../detections/pages/detection_engine/rules/details'; +import { getRuleDetailsTabUrl } from '../../../../common/components/link_to/redirect_to_detection_engine'; + +const StyledFlexItem = styled(EuiFlexItem)` + border-right: 1px solid #d3dae6; + padding: 4px 12px 4px 0; +`; + +export interface ExceptionItemCardMetaInfoProps { + item: ExceptionListItemSchema; + references: RuleReferenceSchema[]; + dataTestSubj: string; +} + +export const ExceptionItemCardMetaInfo = memo( + ({ item, references, dataTestSubj }) => { + const [isPopoverOpen, setIsPopoverOpen] = useState(false); + + const onAffectedRulesClick = () => setIsPopoverOpen((isOpen) => !isOpen); + const onClosePopover = () => setIsPopoverOpen(false); + + const itemActions = useMemo((): EuiContextMenuPanelProps['items'] => { + if (references == null) { + return []; + } + return references.map((reference) => ( + + + + {reference.name} + + + + )); + }, [references, dataTestSubj]); + + return ( + + + } + value2={item.created_by} + dataTestSubj={`${dataTestSubj}-createdBy`} + /> + + + } + value2={item.updated_by} + dataTestSubj={`${dataTestSubj}-updatedBy`} + /> + + + + {i18n.AFFECTED_RULES(references?.length ?? 0)} + + } + panelPaddingSize="none" + isOpen={isPopoverOpen} + closePopover={onClosePopover} + data-test-subj={`${dataTestSubj}-items`} + > + + + + + ); + } +); +ExceptionItemCardMetaInfo.displayName = 'ExceptionItemCardMetaInfo'; + +interface MetaInfoDetailsProps { + fieldName: string; + label: string; + value1: JSX.Element | string; + value2: string; + dataTestSubj: string; +} + +const MetaInfoDetails = memo(({ label, value1, value2, dataTestSubj }) => { + return ( + + + + {label} + + + + + {value1} + + + + + {i18n.EXCEPTION_ITEM_META_BY} + + + + + + + {value2} + + + + + + ); +}); + +MetaInfoDetails.displayName = 'MetaInfoDetails'; diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item_card/translations.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/exception_item_card/translations.ts similarity index 84% rename from x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item_card/translations.ts rename to x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/exception_item_card/translations.ts index 5d462436973552..ccdd5eebf3b8cd 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item_card/translations.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/exception_item_card/translations.ts @@ -10,14 +10,28 @@ import { i18n } from '@kbn/i18n'; export const EXCEPTION_ITEM_EDIT_BUTTON = i18n.translate( 'xpack.securitySolution.exceptions.exceptionItem.editItemButton', { - defaultMessage: 'Edit item', + defaultMessage: 'Edit rule exception', } ); export const EXCEPTION_ITEM_DELETE_BUTTON = i18n.translate( 'xpack.securitySolution.exceptions.exceptionItem.deleteItemButton', { - defaultMessage: 'Delete item', + defaultMessage: 'Delete rule exception', + } +); + +export const ENDPOINT_EXCEPTION_ITEM_EDIT_BUTTON = i18n.translate( + 'xpack.securitySolution.exceptions.exceptionItem.endpoint.editItemButton', + { + defaultMessage: 'Edit endpoint exception', + } +); + +export const ENDPOINT_EXCEPTION_ITEM_DELETE_BUTTON = i18n.translate( + 'xpack.securitySolution.exceptions.exceptionItem.endpoint.deleteItemButton', + { + defaultMessage: 'Delete endpoint exception', } ); @@ -159,3 +173,9 @@ export const OS_MAC = i18n.translate( defaultMessage: 'Mac', } ); + +export const AFFECTED_RULES = (numRules: number) => + i18n.translate('xpack.securitySolution.exceptions.exceptionItem.affectedRules', { + values: { numRules }, + defaultMessage: 'Affects {numRules} {numRules, plural, =1 {rule} other {rules}}', + }); diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/add_exception_comments.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/item_comments/index.tsx similarity index 88% rename from x-pack/plugins/security_solution/public/common/components/exceptions/add_exception_comments.tsx rename to x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/item_comments/index.tsx index aa927eef34d76a..c83e7296698139 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/add_exception_comments.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/item_comments/index.tsx @@ -18,11 +18,11 @@ import { EuiText, } from '@elastic/eui'; import type { Comment } from '@kbn/securitysolution-io-ts-list-types'; -import * as i18n from './translations'; -import { useCurrentUser } from '../../lib/kibana'; -import { getFormattedComments } from './helpers'; +import * as i18n from '../../utils/translations'; +import { useCurrentUser } from '../../../../common/lib/kibana'; +import { getFormattedComments } from '../../utils/helpers'; -interface AddExceptionCommentsProps { +interface ExceptionItemCommentsProps { exceptionItemComments?: Comment[]; newCommentValue: string; newCommentOnChange: (value: string) => void; @@ -45,11 +45,11 @@ const CommentAccordion = styled(EuiAccordion)` `} `; -export const AddExceptionComments = memo(function AddExceptionComments({ +export const ExceptionItemComments = memo(function ExceptionItemComments({ exceptionItemComments, newCommentValue, newCommentOnChange, -}: AddExceptionCommentsProps) { +}: ExceptionItemCommentsProps) { const [shouldShowComments, setShouldShowComments] = useState(false); const currentUser = useCurrentUser(); @@ -71,7 +71,7 @@ export const AddExceptionComments = memo(function AddExceptionComments({ const commentsAccordionTitle = useMemo(() => { if (exceptionItemComments && exceptionItemComments.length > 0) { return ( - + {!shouldShowComments ? i18n.COMMENTS_SHOW(exceptionItemComments.length) : i18n.COMMENTS_HIDE(exceptionItemComments.length)} @@ -97,7 +97,7 @@ export const AddExceptionComments = memo(function AddExceptionComments({ id={'add-exception-comments-accordion'} buttonClassName={COMMENT_ACCORDION_BUTTON_CLASS_NAME} buttonContent={commentsAccordionTitle} - data-test-subj="addExceptionCommentsAccordion" + data-test-subj="ExceptionItemCommentsAccordion" onToggle={(isOpen) => handleTriggerOnClick(isOpen)} > diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/value_with_space_warning/__tests__/__snapshots__/value_with_space_warning.test.tsx.snap b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/value_with_space_warning/__tests__/__snapshots__/value_with_space_warning.test.tsx.snap similarity index 100% rename from x-pack/plugins/security_solution/public/common/components/exceptions/viewer/value_with_space_warning/__tests__/__snapshots__/value_with_space_warning.test.tsx.snap rename to x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/value_with_space_warning/__tests__/__snapshots__/value_with_space_warning.test.tsx.snap diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/value_with_space_warning/__tests__/use_value_with_space_warning.test.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/value_with_space_warning/__tests__/use_value_with_space_warning.test.ts similarity index 100% rename from x-pack/plugins/security_solution/public/common/components/exceptions/viewer/value_with_space_warning/__tests__/use_value_with_space_warning.test.ts rename to x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/value_with_space_warning/__tests__/use_value_with_space_warning.test.ts diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/value_with_space_warning/__tests__/value_with_space_warning.test.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/value_with_space_warning/__tests__/value_with_space_warning.test.tsx similarity index 100% rename from x-pack/plugins/security_solution/public/common/components/exceptions/viewer/value_with_space_warning/__tests__/value_with_space_warning.test.tsx rename to x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/value_with_space_warning/__tests__/value_with_space_warning.test.tsx diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/value_with_space_warning/index.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/value_with_space_warning/index.ts similarity index 100% rename from x-pack/plugins/security_solution/public/common/components/exceptions/viewer/value_with_space_warning/index.ts rename to x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/value_with_space_warning/index.ts diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/value_with_space_warning/use_value_with_space_warning.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/value_with_space_warning/use_value_with_space_warning.ts similarity index 100% rename from x-pack/plugins/security_solution/public/common/components/exceptions/viewer/value_with_space_warning/use_value_with_space_warning.ts rename to x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/value_with_space_warning/use_value_with_space_warning.ts diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/value_with_space_warning/value_with_space_warning.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/value_with_space_warning/value_with_space_warning.tsx similarity index 100% rename from x-pack/plugins/security_solution/public/common/components/exceptions/viewer/value_with_space_warning/value_with_space_warning.tsx rename to x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/value_with_space_warning/value_with_space_warning.tsx diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/use_add_exception.test.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/logic/use_add_exception.test.tsx similarity index 98% rename from x-pack/plugins/security_solution/public/common/components/exceptions/use_add_exception.test.tsx rename to x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/logic/use_add_exception.test.tsx index a451ee9e4963f8..36446f9ca2a4bc 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/use_add_exception.test.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/logic/use_add_exception.test.tsx @@ -9,7 +9,7 @@ import type { RenderHookResult } from '@testing-library/react-hooks'; import { act, renderHook } from '@testing-library/react-hooks'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { coreMock } from '@kbn/core/public/mocks'; -import { KibanaServices } from '../../lib/kibana'; +import { KibanaServices } from '../../../common/lib/kibana'; import * as alertsApi from '../../../detections/containers/detection_engine/alerts/api'; import * as listsApi from '@kbn/securitysolution-list-api'; @@ -23,7 +23,7 @@ import type { CreateExceptionListItemSchema, UpdateExceptionListItemSchema, } from '@kbn/securitysolution-io-ts-list-types'; -import { TestProviders } from '../../mock'; +import { TestProviders } from '../../../common/mock'; import type { UseAddOrUpdateExceptionProps, ReturnUseAddOrUpdateException, @@ -33,7 +33,7 @@ import { useAddOrUpdateException } from './use_add_exception'; const mockKibanaHttpService = coreMock.createStart().http; const mockKibanaServices = KibanaServices.get as jest.Mock; -jest.mock('../../lib/kibana'); +jest.mock('../../../common/lib/kibana'); jest.mock('@kbn/securitysolution-list-api'); const fetchMock = jest.fn(); diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/use_add_exception.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/logic/use_add_exception.tsx similarity index 98% rename from x-pack/plugins/security_solution/public/common/components/exceptions/use_add_exception.tsx rename to x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/logic/use_add_exception.tsx index c06f4928ad8948..88556d305bb034 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/use_add_exception.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/logic/use_add_exception.tsx @@ -22,8 +22,8 @@ import { } from '../../../detections/components/alerts_table/default_config'; import { getQueryFilter } from '../../../../common/detection_engine/get_query_filter'; import type { Index } from '../../../../common/detection_engine/schemas/common/schemas'; -import { formatExceptionItemForUpdate, prepareExceptionItemsForBulkClose } from './helpers'; -import { useKibana } from '../../lib/kibana'; +import { formatExceptionItemForUpdate, prepareExceptionItemsForBulkClose } from '../utils/helpers'; +import { useKibana } from '../../../common/lib/kibana'; /** * Adds exception items to the list. Also optionally closes alerts. diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/use_fetch_or_create_rule_exception_list.test.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/logic/use_fetch_or_create_rule_exception_list.test.tsx similarity index 100% rename from x-pack/plugins/security_solution/public/common/components/exceptions/use_fetch_or_create_rule_exception_list.test.tsx rename to x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/logic/use_fetch_or_create_rule_exception_list.test.tsx diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/use_fetch_or_create_rule_exception_list.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/logic/use_fetch_or_create_rule_exception_list.tsx similarity index 100% rename from x-pack/plugins/security_solution/public/common/components/exceptions/use_fetch_or_create_rule_exception_list.tsx rename to x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/logic/use_fetch_or_create_rule_exception_list.tsx diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/logic/use_find_references.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/logic/use_find_references.tsx new file mode 100644 index 00000000000000..f30d5aeb598a0e --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/logic/use_find_references.tsx @@ -0,0 +1,89 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useEffect, useMemo, useState } from 'react'; +import type { ListArray } from '@kbn/securitysolution-io-ts-list-types'; + +import type { RuleReferenceSchema } from '../../../../common/detection_engine/schemas/response'; +import { findRuleExceptionReferences } from '../../../detections/containers/detection_engine/rules/api'; +import { useToasts } from '../../../common/lib/kibana'; +import type { FindRulesReferencedByExceptionsListProp } from '../../../detections/containers/detection_engine/rules/types'; +import * as i18n from '../utils/translations'; + +export type ReturnUseFindExceptionListReferences = [boolean, RuleReferences | null]; + +export interface RuleReferences { + [key: string]: RuleReferenceSchema[]; +} +/** + * Hook for finding what rules are referenced by a set of exception lists + * @param ruleExceptionLists array of exception list info stored on a rule + */ +export const useFindExceptionListReferences = ( + ruleExceptionLists: ListArray +): ReturnUseFindExceptionListReferences => { + const toasts = useToasts(); + const [isLoading, setIsLoading] = useState(false); + const [references, setReferences] = useState(null); + const listRefs = useMemo((): FindRulesReferencedByExceptionsListProp[] => { + return ruleExceptionLists.map((list) => { + return { + id: list.id, + listId: list.list_id, + namespaceType: list.namespace_type, + }; + }); + }, [ruleExceptionLists]); + + useEffect(() => { + let isSubscribed = true; + const abortCtrl = new AbortController(); + + const findReferences = async () => { + try { + setIsLoading(true); + + const { references: referencesResults } = await findRuleExceptionReferences({ + lists: listRefs, + signal: abortCtrl.signal, + }); + + const results = referencesResults.reduce((acc, result) => { + const [[key, value]] = Object.entries(result); + + acc[key] = value; + + return acc; + }, {}); + + if (isSubscribed) { + setIsLoading(false); + setReferences(results); + } + } catch (error) { + if (isSubscribed) { + setIsLoading(false); + toasts.addError(error, { title: i18n.ERROR_FETCHING_REFERENCES_TITLE }); + } + } + }; + + if (listRefs.length === 0 && isSubscribed) { + setIsLoading(false); + setReferences(null); + } else { + findReferences(); + } + + return (): void => { + isSubscribed = false; + abortCtrl.abort(); + }; + }, [ruleExceptionLists, listRefs, toasts]); + + return [isLoading, references]; +}; diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/exceptionable_endpoint_fields.json b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/utils/exceptionable_endpoint_fields.json similarity index 100% rename from x-pack/plugins/security_solution/public/common/components/exceptions/exceptionable_endpoint_fields.json rename to x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/utils/exceptionable_endpoint_fields.json diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/exceptionable_linux_fields.json b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/utils/exceptionable_linux_fields.json similarity index 100% rename from x-pack/plugins/security_solution/public/common/components/exceptions/exceptionable_linux_fields.json rename to x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/utils/exceptionable_linux_fields.json diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/exceptionable_windows_mac_fields.json b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/utils/exceptionable_windows_mac_fields.json similarity index 100% rename from x-pack/plugins/security_solution/public/common/components/exceptions/exceptionable_windows_mac_fields.json rename to x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/utils/exceptionable_windows_mac_fields.json diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.test.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/utils/helpers.test.tsx similarity index 100% rename from x-pack/plugins/security_solution/public/common/components/exceptions/helpers.test.tsx rename to x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/utils/helpers.test.tsx diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/utils/helpers.tsx similarity index 99% rename from x-pack/plugins/security_solution/public/common/components/exceptions/helpers.tsx rename to x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/utils/helpers.tsx index c7890f99dc44b7..e4087567de39c0 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/utils/helpers.tsx @@ -42,7 +42,7 @@ import type { AlertData, Flattened } from './types'; import type { Ecs } from '../../../../common/ecs'; import type { CodeSignature } from '../../../../common/ecs/file'; -import { WithCopyToClipboard } from '../../lib/clipboard/with_copy_to_clipboard'; +import { WithCopyToClipboard } from '../../../common/lib/clipboard/with_copy_to_clipboard'; import exceptionableLinuxFields from './exceptionable_linux_fields.json'; import exceptionableWindowsMacFields from './exceptionable_windows_mac_fields.json'; import exceptionableEndpointFields from './exceptionable_endpoint_fields.json'; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/utils/translations.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/utils/translations.ts new file mode 100644 index 00000000000000..8f189c7aaf7db3 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/utils/translations.ts @@ -0,0 +1,143 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; + +export const COMMENTS_SHOW = (comments: number) => + i18n.translate('xpack.securitySolution.exceptions.showCommentsLabel', { + values: { comments }, + defaultMessage: 'Show ({comments}) {comments, plural, =1 {Comment} other {Comments}}', + }); + +export const COMMENTS_HIDE = (comments: number) => + i18n.translate('xpack.securitySolution.exceptions.hideCommentsLabel', { + values: { comments }, + defaultMessage: 'Hide ({comments}) {comments, plural, =1 {Comment} other {Comments}}', + }); + +export const COMMENT_EVENT = i18n.translate('xpack.securitySolution.exceptions.commentEventLabel', { + defaultMessage: 'added a comment', +}); + +export const OPERATING_SYSTEM_LABEL = i18n.translate( + 'xpack.securitySolution.exceptions.operatingSystemFullLabel', + { + defaultMessage: 'Operating System', + } +); + +export const ADD_TO_ENDPOINT_LIST = i18n.translate( + 'xpack.securitySolution.exceptions.viewer.addToEndpointListLabel', + { + defaultMessage: 'Add endpoint exception', + } +); + +export const ADD_TO_DETECTIONS_LIST = i18n.translate( + 'xpack.securitySolution.exceptions.viewer.addToDetectionsListLabel', + { + defaultMessage: 'Add rule exception', + } +); + +export const ADD_COMMENT_PLACEHOLDER = i18n.translate( + 'xpack.securitySolution.exceptions.viewer.addCommentPlaceholder', + { + defaultMessage: 'Add a new comment...', + } +); + +export const ADD_TO_CLIPBOARD = i18n.translate( + 'xpack.securitySolution.exceptions.viewer.addToClipboard', + { + defaultMessage: 'Comment', + } +); + +export const CLEAR_EXCEPTIONS_LABEL = i18n.translate( + 'xpack.securitySolution.exceptions.clearExceptionsLabel', + { + defaultMessage: 'Remove Exception List', + } +); + +export const ADD_EXCEPTION_FETCH_404_ERROR = (listId: string) => + i18n.translate('xpack.securitySolution.exceptions.fetch404Error', { + values: { listId }, + defaultMessage: + 'The associated exception list ({listId}) no longer exists. Please remove the missing exception list to add additional exceptions to the detection rule.', + }); + +export const ADD_EXCEPTION_FETCH_ERROR = i18n.translate( + 'xpack.securitySolution.exceptions.fetchError', + { + defaultMessage: 'Error fetching exception list', + } +); + +export const ERROR = i18n.translate('xpack.securitySolution.exceptions.errorLabel', { + defaultMessage: 'Error', +}); + +export const CANCEL = i18n.translate('xpack.securitySolution.exceptions.cancelLabel', { + defaultMessage: 'Cancel', +}); + +export const MODAL_ERROR_ACCORDION_TEXT = i18n.translate( + 'xpack.securitySolution.exceptions.modalErrorAccordionText', + { + defaultMessage: 'Show rule reference information:', + } +); + +export const DISSASOCIATE_LIST_SUCCESS = (id: string) => + i18n.translate('xpack.securitySolution.exceptions.dissasociateListSuccessText', { + values: { id }, + defaultMessage: 'Exception list ({id}) has successfully been removed', + }); + +export const DISSASOCIATE_EXCEPTION_LIST_ERROR = i18n.translate( + 'xpack.securitySolution.exceptions.dissasociateExceptionListError', + { + defaultMessage: 'Failed to remove exception list', + } +); + +export const OPERATING_SYSTEM_WINDOWS = i18n.translate( + 'xpack.securitySolution.exceptions.operatingSystemWindows', + { + defaultMessage: 'Windows', + } +); + +export const OPERATING_SYSTEM_MAC = i18n.translate( + 'xpack.securitySolution.exceptions.operatingSystemMac', + { + defaultMessage: 'macOS', + } +); + +export const OPERATING_SYSTEM_WINDOWS_AND_MAC = i18n.translate( + 'xpack.securitySolution.exceptions.operatingSystemWindowsAndMac', + { + defaultMessage: 'Windows and macOS', + } +); + +export const OPERATING_SYSTEM_LINUX = i18n.translate( + 'xpack.securitySolution.exceptions.operatingSystemLinux', + { + defaultMessage: 'Linux', + } +); + +export const ERROR_FETCHING_REFERENCES_TITLE = i18n.translate( + 'xpack.securitySolution.exceptions.fetchingReferencesErrorToastTitle', + { + defaultMessage: 'Error fetching exception references', + } +); diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/types.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/utils/types.ts similarity index 83% rename from x-pack/plugins/security_solution/public/common/components/exceptions/types.ts rename to x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/utils/types.ts index fe0f137800d26a..56db2ad8257f84 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/types.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/utils/types.ts @@ -11,21 +11,10 @@ import type { CodeSignature } from '../../../../common/ecs/file'; export interface ExceptionListItemIdentifiers { id: string; + name: string; namespaceType: NamespaceType; } -export interface FilterOptions { - filter: string; - tags: string[]; -} - -export interface Filter { - filter: Partial; - pagination: Partial; - showDetectionsListsOnly: boolean; - showEndpointListsOnly: boolean; -} - export interface ExceptionsPagination { pageIndex: number; pageSize: number; diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.tsx index 436c4f63ac77c4..0127fe63efea7f 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.tsx @@ -17,17 +17,17 @@ import { DEFAULT_ACTION_BUTTON_WIDTH } from '@kbn/timelines-plugin/public'; import { useOsqueryContextActionItem } from '../../osquery/use_osquery_context_action_item'; import { OsqueryFlyout } from '../../osquery/osquery_flyout'; import { useRouteSpy } from '../../../../common/utils/route/use_route_spy'; -import { buildGetAlertByIdQuery } from '../../../../common/components/exceptions/helpers'; +import { buildGetAlertByIdQuery } from '../../../../detection_engine/rule_exceptions/utils/helpers'; import { useUserPrivileges } from '../../../../common/components/user_privileges'; import { EventsTdContent } from '../../../../timelines/components/timeline/styles'; import type { Ecs } from '../../../../../common/ecs'; -import type { AddExceptionFlyoutProps } from '../../../../common/components/exceptions/add_exception_flyout'; -import { AddExceptionFlyout } from '../../../../common/components/exceptions/add_exception_flyout'; +import type { AddExceptionFlyoutProps } from '../../../../detection_engine/rule_exceptions/components/add_exception_flyout'; +import { AddExceptionFlyout } from '../../../../detection_engine/rule_exceptions/components/add_exception_flyout'; import * as i18n from '../translations'; import type { inputsModel, State } from '../../../../common/store'; import { inputsSelectors } from '../../../../common/store'; import { TimelineId } from '../../../../../common/types'; -import type { AlertData, EcsHit } from '../../../../common/components/exceptions/types'; +import type { AlertData, EcsHit } from '../../../../detection_engine/rule_exceptions/utils/types'; import { useQueryAlerts } from '../../../containers/detection_engine/alerts/use_query'; import { ALERTS_QUERY_NAMES } from '../../../containers/detection_engine/alerts/constants'; import { useSignalIndex } from '../../../containers/detection_engine/alerts/use_signal_index'; diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/use_investigate_in_timeline.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/use_investigate_in_timeline.tsx index 577ecca52c59e4..ce5b7ee9c5de53 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/use_investigate_in_timeline.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/use_investigate_in_timeline.tsx @@ -73,7 +73,6 @@ export const useInvestigateInTimeline = ({ if (exceptionsLists.length > 0) { await getExceptionListsItems({ lists: exceptionsLists, - filterOptions: [], pagination: { page: 0, perPage: 10000, diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.test.ts b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.test.ts index 48fa12f03565f4..2511e8da834f0a 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.test.ts +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.test.ts @@ -20,6 +20,7 @@ import { fetchTags, getPrePackagedRulesStatus, previewRule, + findRuleExceptionReferences, } from './api'; import { getRulesSchemaMock } from '../../../../../common/detection_engine/schemas/response/rules_schema.mocks'; import { @@ -28,6 +29,8 @@ import { } from '../../../../../common/detection_engine/schemas/request/rule_schemas.mock'; import { getPatchRulesSchemaMock } from '../../../../../common/detection_engine/schemas/request/patch_rules_schema.mock'; import { rulesMock } from './mock'; +import type { FindRulesReferencedByExceptionsListProp } from './types'; +import { DETECTION_ENGINE_RULES_EXCEPTIONS_REFERENCE_URL } from '../../../../../common/constants'; const abortCtrl = new AbortController(); const mockKibanaServices = KibanaServices.get as jest.Mock; @@ -664,4 +667,36 @@ describe('Detections Rules API', () => { expect(resp).toEqual(prePackagedRulesStatus); }); }); + + describe('findRuleExceptionReferences', () => { + beforeEach(() => { + fetchMock.mockClear(); + fetchMock.mockResolvedValue(getRulesSchemaMock()); + }); + + test('GETs exception references', async () => { + const payload: FindRulesReferencedByExceptionsListProp[] = [ + { + id: '123', + listId: 'list_id_1', + namespaceType: 'single', + }, + { + id: '456', + listId: 'list_id_2', + namespaceType: 'single', + }, + ]; + await findRuleExceptionReferences({ lists: payload, signal: abortCtrl.signal }); + expect(fetchMock).toHaveBeenCalledWith(DETECTION_ENGINE_RULES_EXCEPTIONS_REFERENCE_URL, { + query: { + ids: '123,456', + list_ids: 'list_id_1,list_id_2', + namespace_types: 'single,single', + }, + method: 'GET', + signal: abortCtrl.signal, + }); + }); + }); }); diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.ts b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.ts index 876a3a0a469a8e..f2e78eeee99ef3 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.ts +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.ts @@ -17,6 +17,7 @@ import { DETECTION_ENGINE_RULES_PREVIEW, DETECTION_ENGINE_INSTALLED_INTEGRATIONS_URL, DETECTION_ENGINE_RULES_URL_FIND, + DETECTION_ENGINE_RULES_EXCEPTIONS_REFERENCE_URL, } from '../../../../../common/constants'; import type { BulkAction } from '../../../../../common/detection_engine/schemas/request/perform_bulk_action_schema'; import type { @@ -26,6 +27,7 @@ import type { import type { RulesSchema, GetInstalledIntegrationsResponse, + RulesReferencedByExceptionListsSchema, } from '../../../../../common/detection_engine/schemas/response'; import type { @@ -43,6 +45,7 @@ import type { BulkActionProps, BulkActionResponseMap, PreviewRulesProps, + FindRulesReferencedByExceptionsProps, } from './types'; import { KibanaServices } from '../../../../common/lib/kibana'; import * as i18n from '../../../pages/detection_engine/rules/translations'; @@ -369,3 +372,28 @@ export const fetchInstalledIntegrations = async ({ signal, } ); + +/** + * Fetch info on what exceptions lists are referenced by what rules + * + * @param lists exception list information needed for making request + * @param signal to cancel request + * + * @throws An error if response is not OK + */ +export const findRuleExceptionReferences = async ({ + lists, + signal, +}: FindRulesReferencedByExceptionsProps): Promise => + KibanaServices.get().http.fetch( + DETECTION_ENGINE_RULES_EXCEPTIONS_REFERENCE_URL, + { + method: 'GET', + query: { + ids: lists.map(({ id }) => id).join(','), + list_ids: lists.map(({ listId }) => listId).join(','), + namespace_types: lists.map(({ namespaceType }) => namespaceType).join(','), + }, + signal, + } + ); diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/types.ts b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/types.ts index 45c89c307de4ef..77811b3d8aa2df 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/types.ts +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/types.ts @@ -7,6 +7,7 @@ import * as t from 'io-ts'; +import type { NamespaceType } from '@kbn/securitysolution-io-ts-list-types'; import { listArray } from '@kbn/securitysolution-io-ts-list-types'; import type { Type } from '@kbn/securitysolution-io-ts-alerting-types'; import { @@ -341,3 +342,14 @@ export interface PrePackagedRulesStatusResponse { timelines_not_installed: number; timelines_not_updated: number; } + +export interface FindRulesReferencedByExceptionsListProp { + id: string; + listId: string; + namespaceType: NamespaceType; +} + +export interface FindRulesReferencedByExceptionsProps { + lists: FindRulesReferencedByExceptionsListProp[]; + signal?: AbortSignal; +} diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.test.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.test.tsx index 66892235a0f91f..6c5ff0ab2851e5 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.test.tsx @@ -294,4 +294,70 @@ describe('RuleDetailsPageComponent', () => { }); }); }); + + it('renders exceptions tab', async () => { + await setup(); + (useRuleWithFallback as jest.Mock).mockReturnValue({ + error: null, + loading: false, + isExistingRule: true, + refresh: jest.fn(), + rule: { + ...mockRule, + outcome: 'conflict', + alias_target_id: 'aliased_rule_id', + alias_purpose: 'savedObjectConversion', + }, + }); + const wrapper = mount( + + + + + + ); + await waitFor(() => { + expect(wrapper.find('[data-test-subj="navigation-rule_exceptions"]').exists()).toBeTruthy(); + expect( + wrapper.find('[data-test-subj="navigation-endpoint_exceptions"]').exists() + ).toBeFalsy(); + }); + }); + + it('renders endpoint exeptions tab when rule includes endpoint list', async () => { + await setup(); + (useRuleWithFallback as jest.Mock).mockReturnValue({ + error: null, + loading: false, + isExistingRule: true, + refresh: jest.fn(), + rule: { + ...mockRule, + outcome: 'conflict', + alias_target_id: 'aliased_rule_id', + alias_purpose: 'savedObjectConversion', + exceptions_list: [ + { + id: 'endpoint_list', + list_id: 'endpoint_list', + type: 'endpoint', + namespace_type: 'agnostic', + }, + ], + }, + }); + const wrapper = mount( + + + + + + ); + await waitFor(() => { + expect(wrapper.find('[data-test-subj="navigation-rule_exceptions"]').exists()).toBeTruthy(); + expect( + wrapper.find('[data-test-subj="navigation-endpoint_exceptions"]').exists() + ).toBeTruthy(); + }); + }); }); diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx index 0660df924f56af..cc36e6f75da4b0 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx @@ -26,7 +26,6 @@ import { Switch, useParams } from 'react-router-dom'; import type { ConnectedProps } from 'react-redux'; import { connect, useDispatch } from 'react-redux'; import styled from 'styled-components'; -import type { ExceptionListIdentifiers } from '@kbn/securitysolution-io-ts-list-types'; import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; import type { Dispatch } from 'redux'; @@ -79,8 +78,7 @@ import { hasMlLicense } from '../../../../../../common/machine_learning/has_ml_l import { SecurityPageName } from '../../../../../app/types'; import { LinkButton } from '../../../../../common/components/links'; import { useFormatUrl } from '../../../../../common/components/link_to'; -import { ExceptionsViewer } from '../../../../../common/components/exceptions/viewer'; -import { APP_UI_ID, DEFAULT_INDEX_PATTERN } from '../../../../../../common/constants'; +import { APP_UI_ID } from '../../../../../../common/constants'; import { useGlobalFullScreen } from '../../../../../common/containers/use_full_screen'; import { Display } from '../../../../../hosts/pages/display'; @@ -127,6 +125,7 @@ import { } from '../../../../components/alerts_table/alerts_filter_group'; import { useSignalHelpers } from '../../../../../common/containers/sourcerer/use_signal_helpers'; import { HeaderPage } from '../../../../../common/components/header_page'; +import { ExceptionsViewer } from '../../../../../detection_engine/rule_exceptions/components/all_exception_items_table'; import type { NavTab } from '../../../../../common/components/navigation/types'; /** @@ -148,6 +147,7 @@ const StyledMinHeightTabContainer = styled.div` export enum RuleDetailTabs { alerts = 'alerts', exceptions = 'rule_exceptions', + endpointExceptions = 'endpoint_exceptions', executionResults = 'execution_results', executionEvents = 'execution_events', } @@ -155,6 +155,7 @@ export enum RuleDetailTabs { export const RULE_DETAILS_TAB_NAME: Record = { [RuleDetailTabs.alerts]: detectionI18n.ALERT, [RuleDetailTabs.exceptions]: i18n.EXCEPTIONS_TAB, + [RuleDetailTabs.endpointExceptions]: i18n.ENDPOINT_EXCEPTIONS_TAB, [RuleDetailTabs.executionResults]: i18n.EXECUTION_RESULTS_TAB, [RuleDetailTabs.executionEvents]: i18n.EXECUTION_EVENTS_TAB, }; @@ -220,7 +221,6 @@ const RuleDetailsPageComponent: React.FC = ({ runtimeMappings, loading: isLoadingIndexPattern, } = useSourcererDataView(SourcererScopeName.detections); - const loading = userInfoLoading || listsConfigLoading; const { detailName: ruleId } = useParams<{ detailName: string; @@ -247,9 +247,15 @@ const RuleDetailsPageComponent: React.FC = ({ [RuleDetailTabs.exceptions]: { id: RuleDetailTabs.exceptions, name: RULE_DETAILS_TAB_NAME[RuleDetailTabs.exceptions], - disabled: false, + disabled: rule == null, href: `/rules/id/${ruleId}/${RuleDetailTabs.exceptions}`, }, + [RuleDetailTabs.endpointExceptions]: { + id: RuleDetailTabs.endpointExceptions, + name: RULE_DETAILS_TAB_NAME[RuleDetailTabs.endpointExceptions], + disabled: rule == null, + href: `/rules/id/${ruleId}/${RuleDetailTabs.endpointExceptions}`, + }, [RuleDetailTabs.executionResults]: { id: RuleDetailTabs.executionResults, name: RULE_DETAILS_TAB_NAME[RuleDetailTabs.executionResults], @@ -263,10 +269,11 @@ const RuleDetailsPageComponent: React.FC = ({ href: `/rules/id/${ruleId}/${RuleDetailTabs.executionEvents}`, }, }), - [isExistingRule, ruleId] + [isExistingRule, rule, ruleId] ); const [pageTabs, setTabs] = useState>>(ruleDetailTabs); + const { aboutRuleData, modifiedAboutRuleDetailsData, defineRuleData, scheduleRuleData } = rule != null ? getStepsData({ rule, detailsView: true }) @@ -389,11 +396,19 @@ const RuleDetailsPageComponent: React.FC = ({ if (!ruleExecutionSettings.extendedLogging.isEnabled) { hiddenTabs.push(RuleDetailTabs.executionEvents); } + if (rule != null) { + const hasEndpointList = (rule.exceptions_list ?? []).some( + (list) => list.type === ExceptionListTypeEnum.ENDPOINT + ); + if (!hasEndpointList) { + hiddenTabs.push(RuleDetailTabs.endpointExceptions); + } + } const tabs = omit>(hiddenTabs, ruleDetailTabs); setTabs(tabs); - }, [hasIndexRead, ruleDetailTabs, ruleExecutionSettings]); + }, [hasIndexRead, rule, ruleDetailTabs, ruleExecutionSettings]); const showUpdating = useMemo( () => isLoadingIndexPattern || isAlertsLoading || loading, @@ -611,34 +626,6 @@ const RuleDetailsPageComponent: React.FC = ({ [setShowOnlyThreatIndicatorAlerts] ); - const exceptionLists = useMemo((): { - lists: ExceptionListIdentifiers[]; - allowedExceptionListTypes: ExceptionListTypeEnum[]; - } => { - if (rule != null && rule.exceptions_list != null) { - return rule.exceptions_list.reduce<{ - lists: ExceptionListIdentifiers[]; - allowedExceptionListTypes: ExceptionListTypeEnum[]; - }>( - (acc, { id, list_id: listId, namespace_type: namespaceType, type }) => { - const { allowedExceptionListTypes, lists } = acc; - const shouldAddEndpoint = - type === ExceptionListTypeEnum.ENDPOINT && - !allowedExceptionListTypes.includes(ExceptionListTypeEnum.ENDPOINT); - return { - lists: [...lists, { id, listId, namespaceType, type }], - allowedExceptionListTypes: shouldAddEndpoint - ? [...allowedExceptionListTypes, ExceptionListTypeEnum.ENDPOINT] - : allowedExceptionListTypes, - }; - }, - { lists: [], allowedExceptionListTypes: [ExceptionListTypeEnum.DETECTION] } - ); - } else { - return { lists: [], allowedExceptionListTypes: [ExceptionListTypeEnum.DETECTION] }; - } - }, [rule]); - const onSkipFocusBeforeEventsTable = useCallback(() => { focusUtilityBarAction(containerElement.current); }, [containerElement]); @@ -858,14 +845,20 @@ const RuleDetailsPageComponent: React.FC = ({ + + + diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/translations.ts b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/translations.ts index 02e8e01a281e98..1a50d570ea1791 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/translations.ts +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/translations.ts @@ -42,6 +42,13 @@ export const EXCEPTIONS_TAB = i18n.translate( } ); +export const ENDPOINT_EXCEPTIONS_TAB = i18n.translate( + 'xpack.securitySolution.detectionEngine.ruleDetails.endpointExceptionsTab', + { + defaultMessage: 'Endpoint exceptions', + } +); + export const EXECUTION_RESULTS_TAB = i18n.translate( 'xpack.securitySolution.detectionEngine.ruleDetails.ruleExecutionResultsTab', { diff --git a/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/utils/get_formatted_comments.tsx b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/utils/get_formatted_comments.tsx index a75d2a76ae7043..0d4c8caf892b25 100644 --- a/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/utils/get_formatted_comments.tsx +++ b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/utils/get_formatted_comments.tsx @@ -10,7 +10,7 @@ import type { EuiCommentProps } from '@elastic/eui'; import { EuiAvatar, EuiText } from '@elastic/eui'; import styled from 'styled-components'; import type { CommentsArray } from '@kbn/securitysolution-io-ts-list-types'; -import { COMMENT_EVENT } from '../../../../common/components/exceptions/translations'; +import { COMMENT_EVENT } from '../../../../detection_engine/rule_exceptions/utils/translations'; import { FormattedRelativePreferenceDate } from '../../../../common/components/formatted_date'; const CustomEuiAvatar = styled(EuiAvatar)` diff --git a/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/form.tsx b/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/form.tsx index f157a7e4d804ed..f3431de72d7ce6 100644 --- a/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/form.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/form.tsx @@ -29,13 +29,11 @@ import { getExceptionBuilderComponentLazy } from '@kbn/lists-plugin/public'; import type { OnChangeProps } from '@kbn/lists-plugin/public'; import { useTestIdGenerator } from '../../../../hooks/use_test_id_generator'; import type { PolicyData } from '../../../../../../common/endpoint/types'; -import { AddExceptionComments } from '../../../../../common/components/exceptions/add_exception_comments'; import { useFetchIndex } from '../../../../../common/containers/source'; import { Loader } from '../../../../../common/components/loader'; import { useLicense } from '../../../../../common/hooks/use_license'; import { useKibana } from '../../../../../common/lib/kibana'; import type { ArtifactFormComponentProps } from '../../../../components/artifact_list_page'; -import { filterIndexPatterns } from '../../../../../common/components/exceptions/helpers'; import { isArtifactGlobal, getPolicyIdsFromArtifact, @@ -57,6 +55,8 @@ import { ENDPOINT_EVENT_FILTERS_LIST_ID, EVENT_FILTER_LIST_TYPE } from '../../co import type { EffectedPolicySelection } from '../../../../components/effected_policy_select'; import { EffectedPolicySelect } from '../../../../components/effected_policy_select'; import { isGlobalPolicyEffected } from '../../../../components/effected_policy_select/utils'; +import { ExceptionItemComments } from '../../../../../detection_engine/rule_exceptions/components/item_comments'; +import { filterIndexPatterns } from '../../../../../detection_engine/rule_exceptions/utils/helpers'; const OPERATING_SYSTEMS: readonly OperatingSystem[] = [ OperatingSystem.MAC, @@ -316,7 +316,7 @@ export const EventFiltersForm: React.FC ( - { +// FLAKY: https://github.com/elastic/kibana/issues/140153 +describe.skip('When on the policy list page', () => { let render: () => ReturnType; let renderResult: ReturnType; let history: AppContextTestRender['history']; diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/tabs/policy_tabs.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/tabs/policy_tabs.tsx index 7449a0c81afb40..b9a7e1cda040ea 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/tabs/policy_tabs.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/tabs/policy_tabs.tsx @@ -336,7 +336,7 @@ export const PolicyTabs = React.memo(() => { // show loader for privileges validation if ( isInHostIsolationExceptionsTab && - (privileges.loading || allPolicyHostIsolationExceptionsListRequest.isLoading) + (privileges.loading || allPolicyHostIsolationExceptionsListRequest.isFetching) ) { return ; } diff --git a/x-pack/plugins/security_solution/public/rules/routes.tsx b/x-pack/plugins/security_solution/public/rules/routes.tsx index 0ca80c735344ff..633b4005110af5 100644 --- a/x-pack/plugins/security_solution/public/rules/routes.tsx +++ b/x-pack/plugins/security_solution/public/rules/routes.tsx @@ -30,7 +30,7 @@ const RulesSubRoutes = [ exact: true, }, { - path: `/rules/id/:detailName/:tabName(${RuleDetailTabs.alerts}|${RuleDetailTabs.exceptions}|${RuleDetailTabs.executionResults}|${RuleDetailTabs.executionEvents})`, + path: `/rules/id/:detailName/:tabName(${RuleDetailTabs.alerts}|${RuleDetailTabs.exceptions}|${RuleDetailTabs.endpointExceptions}|${RuleDetailTabs.executionResults}|${RuleDetailTabs.executionEvents})`, main: RuleDetailsPage, exact: true, }, 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 906b1e3168a706..56682d81bdab14 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 @@ -280,7 +280,13 @@ describe('test endpoint routes', () => { bool: { must_not: { bool: { - should: [{ exists: { field: 'united.agent.upgraded_at' } }], + should: [ + { + match: { + 'united.agent.upgrade_status': 'completed', + }, + }, + ], minimum_should_match: 1, }, }, diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/query_builders.fixtures.ts b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/query_builders.fixtures.ts index 30189459ff167f..c4fc8c8619e7ec 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/query_builders.fixtures.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/query_builders.fixtures.ts @@ -101,8 +101,9 @@ export const expectedCompleteUnitedIndexQuery = { bool: { should: [ { - exists: { - field: 'united.agent.upgraded_at', + match: { + 'united.agent.upgrade_status': + 'completed', }, }, ], @@ -192,7 +193,11 @@ export const expectedCompleteUnitedIndexQuery = { must_not: { bool: { should: [ - { exists: { field: 'united.agent.upgraded_at' } }, + { + match: { + 'united.agent.upgrade_status': 'completed', + }, + }, ], minimum_should_match: 1, }, @@ -296,7 +301,11 @@ export const expectedCompleteUnitedIndexQuery = { must_not: { bool: { should: [ - { exists: { field: 'united.agent.upgraded_at' } }, + { + match: { + 'united.agent.upgrade_status': 'completed', + }, + }, ], minimum_should_match: 1, }, @@ -367,7 +376,13 @@ export const expectedCompleteUnitedIndexQuery = { bool: { must_not: { bool: { - should: [{ exists: { field: 'united.agent.upgraded_at' } }], + should: [ + { + match: { + 'united.agent.upgrade_status': 'completed', + }, + }, + ], minimum_should_match: 1, }, }, 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 7f89444b21fa58..d24ef99323eaec 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 @@ -93,7 +93,7 @@ describe('test filtering endpoint hosts by agent status', () => { const status = ['healthy']; const kuery = buildStatusesKuery(status); const expected = - '(not (united.agent.last_checkin < now-300s AND not ((united.agent.last_checkin_status:error or united.agent.last_checkin_status:degraded) AND not (((united.agent.upgrade_started_at:*) and not (united.agent.upgraded_at:*)) or (not (united.agent.last_checkin:*)) or (united.agent.unenrollment_started_at:*) or (not united.agent.policy_revision_idx:*))) AND not ( ((united.agent.upgrade_started_at:*) and not (united.agent.upgraded_at:*)) or (not (united.agent.last_checkin:*)) or (united.agent.unenrollment_started_at:*) or (not united.agent.policy_revision_idx:*) )) AND not ((united.agent.last_checkin_status:error or united.agent.last_checkin_status:degraded) AND not (((united.agent.upgrade_started_at:*) and not (united.agent.upgraded_at:*)) or (not (united.agent.last_checkin:*)) or (united.agent.unenrollment_started_at:*) or (not united.agent.policy_revision_idx:*))) AND not (((united.agent.upgrade_started_at:*) and not (united.agent.upgraded_at:*)) or (not (united.agent.last_checkin:*)) or (united.agent.unenrollment_started_at:*) or (not united.agent.policy_revision_idx:*)))'; + '(not (united.agent.last_checkin < now-300s AND not ((united.agent.last_checkin_status:error or united.agent.last_checkin_status:degraded) AND not (((united.agent.upgrade_started_at:*) and not (united.agent.upgrade_status:completed)) or (not (united.agent.last_checkin:*)) or (united.agent.unenrollment_started_at:*) or (not united.agent.policy_revision_idx:*))) AND not ( ((united.agent.upgrade_started_at:*) and not (united.agent.upgrade_status:completed)) or (not (united.agent.last_checkin:*)) or (united.agent.unenrollment_started_at:*) or (not united.agent.policy_revision_idx:*) )) AND not ((united.agent.last_checkin_status:error or united.agent.last_checkin_status:degraded) AND not (((united.agent.upgrade_started_at:*) and not (united.agent.upgrade_status:completed)) or (not (united.agent.last_checkin:*)) or (united.agent.unenrollment_started_at:*) or (not united.agent.policy_revision_idx:*))) AND not (((united.agent.upgrade_started_at:*) and not (united.agent.upgrade_status:completed)) or (not (united.agent.last_checkin:*)) or (united.agent.unenrollment_started_at:*) or (not united.agent.policy_revision_idx:*)))'; expect(kuery).toEqual(expected); }); @@ -101,7 +101,7 @@ describe('test filtering endpoint hosts by agent status', () => { const status = ['offline']; const kuery = buildStatusesKuery(status); const expected = - '(united.agent.last_checkin < now-300s AND not ((united.agent.last_checkin_status:error or united.agent.last_checkin_status:degraded) AND not (((united.agent.upgrade_started_at:*) and not (united.agent.upgraded_at:*)) or (not (united.agent.last_checkin:*)) or (united.agent.unenrollment_started_at:*) or (not united.agent.policy_revision_idx:*))) AND not ( ((united.agent.upgrade_started_at:*) and not (united.agent.upgraded_at:*)) or (not (united.agent.last_checkin:*)) or (united.agent.unenrollment_started_at:*) or (not united.agent.policy_revision_idx:*) ))'; + '(united.agent.last_checkin < now-300s AND not ((united.agent.last_checkin_status:error or united.agent.last_checkin_status:degraded) AND not (((united.agent.upgrade_started_at:*) and not (united.agent.upgrade_status:completed)) or (not (united.agent.last_checkin:*)) or (united.agent.unenrollment_started_at:*) or (not united.agent.policy_revision_idx:*))) AND not ( ((united.agent.upgrade_started_at:*) and not (united.agent.upgrade_status:completed)) or (not (united.agent.last_checkin:*)) or (united.agent.unenrollment_started_at:*) or (not united.agent.policy_revision_idx:*) ))'; expect(kuery).toEqual(expected); }); @@ -109,7 +109,7 @@ describe('test filtering endpoint hosts by agent status', () => { const status = ['unhealthy']; const kuery = buildStatusesKuery(status); const expected = - '((united.agent.last_checkin_status:error or united.agent.last_checkin_status:degraded) AND not (((united.agent.upgrade_started_at:*) and not (united.agent.upgraded_at:*)) or (not (united.agent.last_checkin:*)) or (united.agent.unenrollment_started_at:*) or (not united.agent.policy_revision_idx:*)))'; + '((united.agent.last_checkin_status:error or united.agent.last_checkin_status:degraded) AND not (((united.agent.upgrade_started_at:*) and not (united.agent.upgrade_status:completed)) or (not (united.agent.last_checkin:*)) or (united.agent.unenrollment_started_at:*) or (not united.agent.policy_revision_idx:*)))'; expect(kuery).toEqual(expected); }); @@ -117,7 +117,7 @@ describe('test filtering endpoint hosts by agent status', () => { const status = ['updating']; const kuery = buildStatusesKuery(status); const expected = - '(((united.agent.upgrade_started_at:*) and not (united.agent.upgraded_at:*)) or (not (united.agent.last_checkin:*)) or (united.agent.unenrollment_started_at:*) or (not united.agent.policy_revision_idx:*))'; + '(((united.agent.upgrade_started_at:*) and not (united.agent.upgrade_status:completed)) or (not (united.agent.last_checkin:*)) or (united.agent.unenrollment_started_at:*) or (not united.agent.policy_revision_idx:*))'; expect(kuery).toEqual(expected); }); @@ -132,7 +132,7 @@ describe('test filtering endpoint hosts by agent status', () => { const statuses = ['offline', 'unhealthy']; const kuery = buildStatusesKuery(statuses); const expected = - '(united.agent.last_checkin < now-300s AND not ((united.agent.last_checkin_status:error or united.agent.last_checkin_status:degraded) AND not (((united.agent.upgrade_started_at:*) and not (united.agent.upgraded_at:*)) or (not (united.agent.last_checkin:*)) or (united.agent.unenrollment_started_at:*) or (not united.agent.policy_revision_idx:*))) AND not ( ((united.agent.upgrade_started_at:*) and not (united.agent.upgraded_at:*)) or (not (united.agent.last_checkin:*)) or (united.agent.unenrollment_started_at:*) or (not united.agent.policy_revision_idx:*) ) OR (united.agent.last_checkin_status:error or united.agent.last_checkin_status:degraded) AND not (((united.agent.upgrade_started_at:*) and not (united.agent.upgraded_at:*)) or (not (united.agent.last_checkin:*)) or (united.agent.unenrollment_started_at:*) or (not united.agent.policy_revision_idx:*)))'; + '(united.agent.last_checkin < now-300s AND not ((united.agent.last_checkin_status:error or united.agent.last_checkin_status:degraded) AND not (((united.agent.upgrade_started_at:*) and not (united.agent.upgrade_status:completed)) or (not (united.agent.last_checkin:*)) or (united.agent.unenrollment_started_at:*) or (not united.agent.policy_revision_idx:*))) AND not ( ((united.agent.upgrade_started_at:*) and not (united.agent.upgrade_status:completed)) or (not (united.agent.last_checkin:*)) or (united.agent.unenrollment_started_at:*) or (not united.agent.policy_revision_idx:*) ) OR (united.agent.last_checkin_status:error or united.agent.last_checkin_status:degraded) AND not (((united.agent.upgrade_started_at:*) and not (united.agent.upgrade_status:completed)) or (not (united.agent.last_checkin:*)) or (united.agent.unenrollment_started_at:*) or (not united.agent.policy_revision_idx:*)))'; expect(kuery).toEqual(expected); }); }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/find_rule_exceptions_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/find_rule_exceptions_route.test.ts new file mode 100644 index 00000000000000..1ca0fd4dabf606 --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/find_rule_exceptions_route.test.ts @@ -0,0 +1,154 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { DETECTION_ENGINE_RULES_EXCEPTIONS_REFERENCE_URL } from '../../../../../common/constants'; +import { + getEmptyFindResult, + getFindResultWithSingleHit, + getRuleMock, +} from '../__mocks__/request_responses'; +import { requestContextMock, serverMock, requestMock } from '../__mocks__'; +import { findRuleExceptionReferencesRoute } from './find_rule_exceptions_route'; +import { getQueryRuleParams } from '../../schemas/rule_schemas.mock'; + +describe('findRuleExceptionReferencesRoute', () => { + let server: ReturnType; + let { clients, context } = requestContextMock.createTools(); + + beforeEach(() => { + server = serverMock.create(); + ({ clients, context } = requestContextMock.createTools()); + + clients.rulesClient.find.mockResolvedValue({ + ...getFindResultWithSingleHit(), + data: [ + { + ...getRuleMock({ + ...getQueryRuleParams(), + exceptionsList: [ + { + type: 'detection', + id: '4656dc92-5832-11ea-8e2d-0242ac130003', + list_id: 'my_default_list', + namespace_type: 'single', + }, + ], + }), + }, + ], + }); + + findRuleExceptionReferencesRoute(server.router); + }); + + describe('happy paths', () => { + test('returns 200 when adding an exception item and rule_default exception list already exists', async () => { + const request = requestMock.create({ + method: 'get', + path: `${DETECTION_ENGINE_RULES_EXCEPTIONS_REFERENCE_URL}?exception_list`, + query: { + ids: `4656dc92-5832-11ea-8e2d-0242ac130003`, + list_ids: `my_default_list`, + namespace_types: `single`, + }, + }); + const response = await server.inject(request, requestContextMock.convertContext(context)); + + expect(response.status).toEqual(200); + expect(response.body).toEqual({ + references: [ + { + my_default_list: [ + { + exception_lists: [ + { + id: '4656dc92-5832-11ea-8e2d-0242ac130003', + list_id: 'my_default_list', + namespace_type: 'single', + type: 'detection', + }, + ], + id: '04128c15-0d1b-4716-a4c5-46997ac7f3bd', + name: 'Detect Root/Admin Users', + rule_id: 'rule-1', + }, + ], + }, + ], + }); + }); + + test('returns 200 when no references found', async () => { + const request = requestMock.create({ + method: 'get', + path: DETECTION_ENGINE_RULES_EXCEPTIONS_REFERENCE_URL, + query: { + ids: `4656dc92-5832-11ea-8e2d-0242ac130003`, + list_ids: `my_default_list`, + namespace_types: `single`, + }, + }); + + clients.rulesClient.find.mockResolvedValue(getEmptyFindResult()); + + const response = await server.inject(request, requestContextMock.convertContext(context)); + + expect(response.status).toEqual(200); + expect(response.body).toEqual({ + references: [ + { + my_default_list: [], + }, + ], + }); + }); + }); + + describe('error codes', () => { + test('returns 400 if query param lengths do not match', async () => { + const request = requestMock.create({ + method: 'get', + path: DETECTION_ENGINE_RULES_EXCEPTIONS_REFERENCE_URL, + query: { + ids: `4656dc92-5832-11ea-8e2d-0242ac130003`, + list_ids: `my_default_list`, + namespace_types: `single,agnostic`, + }, + }); + + clients.rulesClient.find.mockResolvedValue(getEmptyFindResult()); + + const response = await server.inject(request, requestContextMock.convertContext(context)); + + expect(response.status).toEqual(400); + expect(response.body).toEqual({ + message: + '"ids", "list_ids" and "namespace_types" need to have the same comma separated number of values. Expected "ids" length: 1 to equal "namespace_types" length: 2 and "list_ids" length: 1.', + status_code: 400, + }); + }); + + test('returns 500 if rules client fails', async () => { + const request = requestMock.create({ + method: 'get', + path: DETECTION_ENGINE_RULES_EXCEPTIONS_REFERENCE_URL, + query: { + ids: `4656dc92-5832-11ea-8e2d-0242ac130003`, + list_ids: `my_default_list`, + namespace_types: `single`, + }, + }); + + clients.rulesClient.find.mockRejectedValue(new Error('find request failed')); + + const response = await server.inject(request, requestContextMock.convertContext(context)); + + expect(response.status).toEqual(500); + expect(response.body).toEqual({ message: 'find request failed', status_code: 500 }); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/find_rule_exceptions_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/find_rule_exceptions_route.ts new file mode 100644 index 00000000000000..8ac258322e260d --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/find_rule_exceptions_route.ts @@ -0,0 +1,95 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { transformError } from '@kbn/securitysolution-es-utils'; +import { getSavedObjectType } from '@kbn/securitysolution-list-utils'; +import { validate } from '@kbn/securitysolution-io-ts-utils'; +import type { FindResult } from '@kbn/alerting-plugin/server'; + +import type { SecuritySolutionPluginRouter } from '../../../../types'; +import { DETECTION_ENGINE_RULES_EXCEPTIONS_REFERENCE_URL } from '../../../../../common/constants'; +import { buildSiemResponse } from '../utils'; +import { enrichFilterWithRuleTypeMapping } from '../../rules/enrich_filter_with_rule_type_mappings'; +import type { FindExceptionReferencesOnRuleSchemaDecoded } from '../../../../../common/detection_engine/schemas/request/find_exception_list_references_schema'; +import { findExceptionReferencesOnRuleSchema } from '../../../../../common/detection_engine/schemas/request/find_exception_list_references_schema'; +import { buildRouteValidation } from '../../../../utils/build_validation/route_validation'; +import type { RuleReferencesSchema } from '../../../../../common/detection_engine/schemas/response/find_exception_list_references_schema'; +import { rulesReferencedByExceptionListsSchema } from '../../../../../common/detection_engine/schemas/response/find_exception_list_references_schema'; +import type { RuleParams } from '../../schemas/rule_schemas'; + +export const findRuleExceptionReferencesRoute = (router: SecuritySolutionPluginRouter) => { + router.get( + { + path: DETECTION_ENGINE_RULES_EXCEPTIONS_REFERENCE_URL, + validate: { + query: buildRouteValidation< + typeof findExceptionReferencesOnRuleSchema, + FindExceptionReferencesOnRuleSchemaDecoded + >(findExceptionReferencesOnRuleSchema), + }, + options: { + tags: ['access:securitySolution'], + }, + }, + async (context, request, response) => { + const siemResponse = buildSiemResponse(response); + + try { + const { ids, namespace_types: namespaceTypes, list_ids: listIds } = request.query; + + const ctx = await context.resolve(['core', 'securitySolution', 'alerting']); + const rulesClient = ctx.alerting.getRulesClient(); + + if (ids.length !== namespaceTypes.length || ids.length !== listIds.length) { + return siemResponse.error({ + body: `"ids", "list_ids" and "namespace_types" need to have the same comma separated number of values. Expected "ids" length: ${ids.length} to equal "namespace_types" length: ${namespaceTypes.length} and "list_ids" length: ${listIds.length}.`, + statusCode: 400, + }); + } + + const foundRules: Array> = await Promise.all( + ids.map(async (id, index) => { + return rulesClient.find({ + options: { + perPage: 10000, + filter: enrichFilterWithRuleTypeMapping(null), + hasReference: { + id, + type: getSavedObjectType({ namespaceType: namespaceTypes[index] }), + }, + }, + }); + }) + ); + + const references = foundRules.map(({ data }, index) => { + const wantedData = data.map(({ name, id, params }) => ({ + name, + id, + rule_id: params.ruleId, + exception_lists: params.exceptionsList, + })); + return { [listIds[index]]: wantedData }; + }); + + const [validated, errors] = validate({ references }, rulesReferencedByExceptionListsSchema); + + if (errors != null) { + return siemResponse.error({ statusCode: 500, body: errors }); + } else { + return response.ok({ body: validated ?? { references: [] } }); + } + } catch (err) { + const error = transformError(err); + return siemResponse.error({ + body: error.message, + statusCode: error.statusCode, + }); + } + } + ); +}; diff --git a/x-pack/plugins/security_solution/server/routes/index.ts b/x-pack/plugins/security_solution/server/routes/index.ts index 5e8e700fcc1e02..af14b3c01226d4 100644 --- a/x-pack/plugins/security_solution/server/routes/index.ts +++ b/x-pack/plugins/security_solution/server/routes/index.ts @@ -74,6 +74,7 @@ import { createPrebuiltSavedObjectsRoute } from '../lib/prebuilt_saved_objects/r import { readAlertsIndexExistsRoute } from '../lib/detection_engine/routes/index/read_alerts_index_exists_route'; import { getInstalledIntegrationsRoute } from '../lib/detection_engine/routes/fleet/get_installed_integrations/get_installed_integrations_route'; import { registerResolverRoutes } from '../endpoint/routes/resolver'; +import { findRuleExceptionReferencesRoute } from '../lib/detection_engine/routes/rules/find_rule_exceptions_route'; import { createRuleExceptionsRoute } from '../lib/detection_engine/routes/rules/create_rule_exceptions_route'; export const initRoutes = ( @@ -132,6 +133,7 @@ export const initRoutes = ( patchTimelinesRoute(router, config, security); importRulesRoute(router, config, ml); exportRulesRoute(router, config, logger); + findRuleExceptionReferencesRoute(router); importTimelinesRoute(router, config, security); exportTimelinesRoute(router, config, security); diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 77e4c5bba571bb..43b3cbacf2a8df 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -25449,17 +25449,12 @@ "xpack.securitySolution.eventsViewer.unit": "{totalCount, plural, =1 {événement} other {événements}}", "xpack.securitySolution.exceptions.dissasociateListSuccessText": "La liste d'exceptions ({id}) a été retirée avec succès", "xpack.securitySolution.exceptions.exceptionItem.showCommentsLabel": "Afficher {comments, plural, =1 {commentaire} other {commentaires}} ({comments})", - "xpack.securitySolution.exceptions.exceptionsPaginationLabel": "Éléments par page : {items}", "xpack.securitySolution.exceptions.failedLoadPolicies": "Une erreur s'est produite lors du chargement des politiques : \"{error}\"", "xpack.securitySolution.exceptions.fetch404Error": "La liste d'exceptions associée ({listId}) n'existe plus. Veuillez retirer la liste d'exceptions manquante pour ajouter des exceptions supplémentaires à la règle de détection.", "xpack.securitySolution.exceptions.hideCommentsLabel": "Masquer ({comments}) {comments, plural, =1 {commentaire} other {commentaires}}", - "xpack.securitySolution.exceptions.paginationNumberOfItemsLabel": "{items} éléments", "xpack.securitySolution.exceptions.referenceModalDescription": "Cette liste d'exceptions est associée à ({referenceCount}) {referenceCount, plural, =1 {règle} other {règles}}. Le retrait de cette liste d'exceptions supprimera également sa référence des règles associées.", "xpack.securitySolution.exceptions.referenceModalSuccessDescription": "Liste d'exceptions - {listId} - supprimée avec succès.", "xpack.securitySolution.exceptions.showCommentsLabel": "Afficher ({comments}) {comments, plural, =1 {commentaire} other {commentaires}}", - "xpack.securitySolution.exceptions.utilityNumberExceptionsLabel": "Affichage de {items} {items, plural, =1 {exception} other {exceptions}}", - "xpack.securitySolution.exceptions.viewer.exceptionDetectionDetailsDescription": "Toutes les exceptions à cette règle sont appliquées à la règle de détection, et non au point de terminaison. Afficher les {ruleSettings} pour plus de détails.", - "xpack.securitySolution.exceptions.viewer.exceptionEndpointDetailsDescription": "Toutes les exceptions à cette règle sont appliquées au point de terminaison et à la règle de détection. Afficher les {ruleSettings} pour plus de détails.", "xpack.securitySolution.fieldBrowser.descriptionForScreenReaderOnly": "Description pour le champ {field} :", "xpack.securitySolution.footer.autoRefreshActiveTooltip": "Lorsque l'actualisation automatique est activée, la chronologie vous montrera les {numberOfItems} derniers événements correspondant à votre recherche.", "xpack.securitySolution.formattedNumber.countsLabel": "{mantissa}{scale}{hasRemainder}", @@ -28026,16 +28021,12 @@ "xpack.securitySolution.exceptions.addException.operatingSystemPlaceHolder": "Sélectionner un système d'exploitation", "xpack.securitySolution.exceptions.addException.sequenceWarning": "La requête de cette règle contient une instruction de séquence EQL. L'exception créée s'appliquera à tous les événements de la séquence.", "xpack.securitySolution.exceptions.addException.success": "Exception ajoutée avec succès", - "xpack.securitySolution.exceptions.andDescription": "AND", "xpack.securitySolution.exceptions.badge.readOnly.tooltip": "Impossible de créer, de modifier ou de supprimer des exceptions", "xpack.securitySolution.exceptions.cancelLabel": "Annuler", "xpack.securitySolution.exceptions.clearExceptionsLabel": "Retirer la liste d'exceptions", "xpack.securitySolution.exceptions.commentEventLabel": "a ajouté un commentaire", - "xpack.securitySolution.exceptions.commentLabel": "Commentaire", - "xpack.securitySolution.exceptions.descriptionLabel": "Description", - "xpack.securitySolution.exceptions.detectionListLabel": "Liste de détection", "xpack.securitySolution.exceptions.dissasociateExceptionListError": "Impossible de retirer la liste d'exceptions", - "xpack.securitySolution.exceptions.editButtonLabel": "Modifier", + "xpack.securitySolution.exceptions.dissasociateListSuccessText": "La liste d'exceptions ({id}) a été retirée avec succès", "xpack.securitySolution.exceptions.editException.bulkCloseLabel": "Fermer toutes les alertes qui correspondent à cette exception et ont été générées par cette règle", "xpack.securitySolution.exceptions.editException.bulkCloseLabel.disabled": "Fermer toutes les alertes qui correspondent à cette exception et ont été générées par cette règle (les listes et les champs non ECS ne sont pas pris en charge)", "xpack.securitySolution.exceptions.editException.cancel": "Annuler", @@ -28048,8 +28039,12 @@ "xpack.securitySolution.exceptions.editException.success": "L'exception a été mise à jour avec succès", "xpack.securitySolution.exceptions.editException.versionConflictDescription": "Cette exception semble avoir été mise à jour depuis que vous l'avez sélectionnée pour la modifier. Essayez de cliquer sur \"Annuler\" et de modifier à nouveau l'exception.", "xpack.securitySolution.exceptions.editException.versionConflictTitle": "Désolé, une erreur est survenue", - "xpack.securitySolution.exceptions.endpointListLabel": "Liste de points de terminaison", "xpack.securitySolution.exceptions.errorLabel": "Erreur", + "xpack.securitySolution.exceptions.failedLoadPolicies": "Une erreur s'est produite lors du chargement des politiques : \"{error}\"", + "xpack.securitySolution.exceptions.fetch404Error": "La liste d'exceptions associée ({listId}) n'existe plus. Veuillez retirer la liste d'exceptions manquante pour ajouter des exceptions supplémentaires à la règle de détection.", + "xpack.securitySolution.exceptions.fetchError": "Erreur lors de la récupération de la liste d'exceptions", + "xpack.securitySolution.exceptions.hideCommentsLabel": "Masquer ({comments}) {comments, plural, =1 {commentaire} other {commentaires}}", + "xpack.securitySolution.exceptions.modalErrorAccordionText": "Afficher les informations de référence de la règle :", "xpack.securitySolution.exceptions.exceptionItem.conditions.and": "AND", "xpack.securitySolution.exceptions.exceptionItem.conditions.existsOperator": "existe", "xpack.securitySolution.exceptions.exceptionItem.conditions.existsOperator.not": "n'existe pas", @@ -28072,37 +28067,21 @@ "xpack.securitySolution.exceptions.exceptionItem.metaDetailsBy": "par", "xpack.securitySolution.exceptions.exceptionItem.updatedLabel": "Mis à jour", "xpack.securitySolution.exceptions.fetchError": "Erreur lors de la récupération de la liste d'exceptions", - "xpack.securitySolution.exceptions.fieldDescription": "Champ", "xpack.securitySolution.exceptions.modalErrorAccordionText": "Afficher les informations de référence de la règle :", - "xpack.securitySolution.exceptions.nameLabel": "Nom", "xpack.securitySolution.exceptions.operatingSystemFullLabel": "Système d'exploitation", "xpack.securitySolution.exceptions.operatingSystemLinux": "Linux", "xpack.securitySolution.exceptions.operatingSystemMac": "macOS", "xpack.securitySolution.exceptions.operatingSystemWindows": "Windows", "xpack.securitySolution.exceptions.operatingSystemWindowsAndMac": "Windows et macOS", - "xpack.securitySolution.exceptions.operatorDescription": "Opérateur", - "xpack.securitySolution.exceptions.orDescription": "OR", "xpack.securitySolution.exceptions.referenceModalCancelButton": "Annuler", "xpack.securitySolution.exceptions.referenceModalDeleteButton": "Retirer la liste d'exceptions", "xpack.securitySolution.exceptions.referenceModalTitle": "Retirer la liste d'exceptions", - "xpack.securitySolution.exceptions.removeButtonLabel": "Retirer", "xpack.securitySolution.exceptions.searchPlaceholder": "par ex. Exemple de liste de noms", - "xpack.securitySolution.exceptions.utilityRefreshLabel": "Actualiser", - "xpack.securitySolution.exceptions.valueDescription": "Valeur", + "xpack.securitySolution.exceptions.showCommentsLabel": "Afficher ({comments}) {comments, plural, =1 {commentaire} other {commentaires}}", "xpack.securitySolution.exceptions.viewer.addCommentPlaceholder": "Ajouter un nouveau commentaire...", - "xpack.securitySolution.exceptions.viewer.addExceptionLabel": "Ajouter une nouvelle exception", "xpack.securitySolution.exceptions.viewer.addToClipboard": "Commentaire", "xpack.securitySolution.exceptions.viewer.addToDetectionsListLabel": "Ajouter une exception à une règle", "xpack.securitySolution.exceptions.viewer.addToEndpointListLabel": "Ajouter une exception de point de terminaison", - "xpack.securitySolution.exceptions.viewer.deleteExceptionError": "Erreur lors de la suppression de l'exception", - "xpack.securitySolution.exceptions.viewer.emptyPromptBody": "Vous pouvez ajouter des exceptions pour affiner la règle de façon à ce que les alertes de détection ne soient pas créées lorsque les conditions d'exception sont remplies. Les exceptions améliorent la précision de la détection, ce qui peut permettre de réduire le nombre de faux positifs.", - "xpack.securitySolution.exceptions.viewer.emptyPromptTitle": "Cette règle ne possède aucune exception", - "xpack.securitySolution.exceptions.viewer.exceptionDetectionDetailsDescription.ruleSettingsLink": "paramètres de règles", - "xpack.securitySolution.exceptions.viewer.exceptionEndpointDetailsDescription.ruleSettingsLink": "paramètres de règles", - "xpack.securitySolution.exceptions.viewer.fetchingListError": "Erreur lors de la récupération des exceptions", - "xpack.securitySolution.exceptions.viewer.fetchTotalsError": "Erreur lors de l'obtention des totaux d'éléments de l'exception", - "xpack.securitySolution.exceptions.viewer.noSearchResultsPromptBody": "Aucun résultat n'a été trouvé pour la recherche.", - "xpack.securitySolution.exceptions.viewer.searchDefaultPlaceholder": "Champ de recherche (ex : host.name)", "xpack.securitySolution.exitFullScreenButton": "Quitter le plein écran", "xpack.securitySolution.expandedValue.hideTopValues.HideTopValues": "Masquer les valeurs les plus élevées", "xpack.securitySolution.expandedValue.links.expandIpDetails": "Développer les détails d'IP", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index bd85b88aef4c80..1d8efe71c1530e 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -25426,17 +25426,12 @@ "xpack.securitySolution.eventsViewer.unit": "{totalCount, plural, other {イベント}}", "xpack.securitySolution.exceptions.dissasociateListSuccessText": "例外リスト({id})が正常に削除されました", "xpack.securitySolution.exceptions.exceptionItem.showCommentsLabel": "{comments, plural, other {件のコメント}}を表示({comments})", - "xpack.securitySolution.exceptions.exceptionsPaginationLabel": "ページごとの項目数:{items}", "xpack.securitySolution.exceptions.failedLoadPolicies": "ポリシーの読み込みエラーが発生しました:\"{error}\"", "xpack.securitySolution.exceptions.fetch404Error": "関連付けられた例外リスト({listId})は存在しません。その他の例外を検出ルールに追加するには、見つからない例外リストを削除してください。", "xpack.securitySolution.exceptions.hideCommentsLabel": "({comments}){comments, plural, other {件のコメント}}を非表示", - "xpack.securitySolution.exceptions.paginationNumberOfItemsLabel": "{items}個の項目", "xpack.securitySolution.exceptions.referenceModalDescription": "この例外リストは、({referenceCount}) {referenceCount, plural, other {個のルール}}に関連付けられています。この例外リストを削除すると、関連付けられたルールからの参照も削除されます。", "xpack.securitySolution.exceptions.referenceModalSuccessDescription": "例外リスト{listId}が正常に削除されました。", "xpack.securitySolution.exceptions.showCommentsLabel": "({comments}){comments, plural, other {件のコメント}}を表示", - "xpack.securitySolution.exceptions.utilityNumberExceptionsLabel": "{items} {items, plural, other {件の例外}}を表示しています", - "xpack.securitySolution.exceptions.viewer.exceptionDetectionDetailsDescription": "このルールのすべての例外は、エンドポイントではなく、検出ルールに適用されます。詳細については、{ruleSettings}を確認してください。", - "xpack.securitySolution.exceptions.viewer.exceptionEndpointDetailsDescription": "このルールのすべての例外は、エンドポイントと検出ルールに適用されます。詳細については、{ruleSettings}を確認してください。", "xpack.securitySolution.fieldBrowser.descriptionForScreenReaderOnly": "フィールド {field} の説明:", "xpack.securitySolution.footer.autoRefreshActiveTooltip": "自動更新が有効な間、タイムラインはクエリに一致する最新の {numberOfItems} 件のイベントを表示します。", "xpack.securitySolution.formattedNumber.countsLabel": "{mantissa}{scale}{hasRemainder}", @@ -28003,16 +27998,12 @@ "xpack.securitySolution.exceptions.addException.operatingSystemPlaceHolder": "オペレーティングシステムを選択", "xpack.securitySolution.exceptions.addException.sequenceWarning": "このルールのクエリにはEQLシーケンス文があります。作成された例外は、シーケンスのすべてのイベントに適用されます。", "xpack.securitySolution.exceptions.addException.success": "正常に例外を追加しました", - "xpack.securitySolution.exceptions.andDescription": "AND", "xpack.securitySolution.exceptions.badge.readOnly.tooltip": "例外を作成、編集、削除できません", "xpack.securitySolution.exceptions.cancelLabel": "キャンセル", "xpack.securitySolution.exceptions.clearExceptionsLabel": "例外リストを削除", "xpack.securitySolution.exceptions.commentEventLabel": "コメントを追加しました", - "xpack.securitySolution.exceptions.commentLabel": "コメント", - "xpack.securitySolution.exceptions.descriptionLabel": "説明", - "xpack.securitySolution.exceptions.detectionListLabel": "検出リスト", "xpack.securitySolution.exceptions.dissasociateExceptionListError": "例外リストを削除できませんでした", - "xpack.securitySolution.exceptions.editButtonLabel": "編集", + "xpack.securitySolution.exceptions.dissasociateListSuccessText": "例外リスト({id})が正常に削除されました", "xpack.securitySolution.exceptions.editException.bulkCloseLabel": "この例外一致し、このルールによって生成された、すべてのアラートを閉じる", "xpack.securitySolution.exceptions.editException.bulkCloseLabel.disabled": "この例外と一致し、このルールによって生成された、すべてのアラートを閉じる(リストと非ECSフィールドはサポートされません)", "xpack.securitySolution.exceptions.editException.cancel": "キャンセル", @@ -28025,8 +28016,11 @@ "xpack.securitySolution.exceptions.editException.success": "正常に例外を更新しました", "xpack.securitySolution.exceptions.editException.versionConflictDescription": "最初に編集することを選択したときからこの例外が更新されている可能性があります。[キャンセル]をクリックし、もう一度例外を編集してください。", "xpack.securitySolution.exceptions.editException.versionConflictTitle": "申し訳ございません、エラーが発生しました", - "xpack.securitySolution.exceptions.endpointListLabel": "エンドポイントリスト", "xpack.securitySolution.exceptions.errorLabel": "エラー", + "xpack.securitySolution.exceptions.failedLoadPolicies": "ポリシーの読み込みエラーが発生しました:\"{error}\"", + "xpack.securitySolution.exceptions.fetch404Error": "関連付けられた例外リスト({listId})は存在しません。その他の例外を検出ルールに追加するには、見つからない例外リストを削除してください。", + "xpack.securitySolution.exceptions.fetchError": "例外リストの取得エラー", + "xpack.securitySolution.exceptions.hideCommentsLabel": "({comments}){comments, plural, other {件のコメント}}を非表示", "xpack.securitySolution.exceptions.exceptionItem.conditions.and": "AND", "xpack.securitySolution.exceptions.exceptionItem.conditions.existsOperator": "存在する", "xpack.securitySolution.exceptions.exceptionItem.conditions.existsOperator.not": "存在しない", @@ -28049,37 +28043,21 @@ "xpack.securitySolution.exceptions.exceptionItem.metaDetailsBy": "グループ基準", "xpack.securitySolution.exceptions.exceptionItem.updatedLabel": "更新しました", "xpack.securitySolution.exceptions.fetchError": "例外リストの取得エラー", - "xpack.securitySolution.exceptions.fieldDescription": "フィールド", "xpack.securitySolution.exceptions.modalErrorAccordionText": "ルール参照情報を表示:", - "xpack.securitySolution.exceptions.nameLabel": "名前", "xpack.securitySolution.exceptions.operatingSystemFullLabel": "オペレーティングシステム", "xpack.securitySolution.exceptions.operatingSystemLinux": "Linux", "xpack.securitySolution.exceptions.operatingSystemMac": "macOS", "xpack.securitySolution.exceptions.operatingSystemWindows": "Windows", "xpack.securitySolution.exceptions.operatingSystemWindowsAndMac": "WindowsおよびmacOS", - "xpack.securitySolution.exceptions.operatorDescription": "演算子", - "xpack.securitySolution.exceptions.orDescription": "OR", "xpack.securitySolution.exceptions.referenceModalCancelButton": "キャンセル", "xpack.securitySolution.exceptions.referenceModalDeleteButton": "例外リストを削除", "xpack.securitySolution.exceptions.referenceModalTitle": "例外リストを削除", - "xpack.securitySolution.exceptions.removeButtonLabel": "削除", "xpack.securitySolution.exceptions.searchPlaceholder": "例:例外リスト名", - "xpack.securitySolution.exceptions.utilityRefreshLabel": "更新", - "xpack.securitySolution.exceptions.valueDescription": "値", + "xpack.securitySolution.exceptions.showCommentsLabel": "({comments}){comments, plural, other {件のコメント}}を表示", "xpack.securitySolution.exceptions.viewer.addCommentPlaceholder": "新しいコメントを追加...", - "xpack.securitySolution.exceptions.viewer.addExceptionLabel": "新しい例外を追加", "xpack.securitySolution.exceptions.viewer.addToClipboard": "コメント", "xpack.securitySolution.exceptions.viewer.addToDetectionsListLabel": "ルール例外の追加", "xpack.securitySolution.exceptions.viewer.addToEndpointListLabel": "エンドポイント例外の追加", - "xpack.securitySolution.exceptions.viewer.deleteExceptionError": "例外の削除エラー", - "xpack.securitySolution.exceptions.viewer.emptyPromptBody": "例外を追加してルールを微調整し、例外条件が満たされたときに検出アラートが作成されないようにすることができます。例外により検出の精度が改善します。これにより、誤検出数が減ります。", - "xpack.securitySolution.exceptions.viewer.emptyPromptTitle": "このルールには例外がありません", - "xpack.securitySolution.exceptions.viewer.exceptionDetectionDetailsDescription.ruleSettingsLink": "ルール設定", - "xpack.securitySolution.exceptions.viewer.exceptionEndpointDetailsDescription.ruleSettingsLink": "ルール設定", - "xpack.securitySolution.exceptions.viewer.fetchingListError": "例外の取得エラー", - "xpack.securitySolution.exceptions.viewer.fetchTotalsError": "例外項目合計数の取得エラー", - "xpack.securitySolution.exceptions.viewer.noSearchResultsPromptBody": "検索結果が見つかりません。", - "xpack.securitySolution.exceptions.viewer.searchDefaultPlaceholder": "検索フィールド(例:host.name)", "xpack.securitySolution.exitFullScreenButton": "全画面を終了", "xpack.securitySolution.expandedValue.hideTopValues.HideTopValues": "上位の値を非表示", "xpack.securitySolution.expandedValue.links.expandIpDetails": "IP詳細を展開", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 722114403f28ef..120a031c7c9121 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -25457,17 +25457,12 @@ "xpack.securitySolution.eventsViewer.unit": "{totalCount, plural, other {个事件}}", "xpack.securitySolution.exceptions.dissasociateListSuccessText": "例外列表 ({id}) 已成功移除", "xpack.securitySolution.exceptions.exceptionItem.showCommentsLabel": "显示{comments, plural, other {注释}} ({comments})", - "xpack.securitySolution.exceptions.exceptionsPaginationLabel": "每页项数:{items}", "xpack.securitySolution.exceptions.failedLoadPolicies": "加载策略时出错:“{error}”", "xpack.securitySolution.exceptions.fetch404Error": "关联的例外列表 ({listId}) 已不存在。请移除缺少的例外列表,以将其他例外添加到检测规则。", "xpack.securitySolution.exceptions.hideCommentsLabel": "隐藏 ({comments}) 个{comments, plural, other {注释}}", - "xpack.securitySolution.exceptions.paginationNumberOfItemsLabel": "{items} 项", "xpack.securitySolution.exceptions.referenceModalDescription": "此例外列表与 ({referenceCount}) 个{referenceCount, plural, other {规则}}关联。移除此例外列表还将会删除其对关联规则的引用。", "xpack.securitySolution.exceptions.referenceModalSuccessDescription": "例外列表 - {listId} - 已成功删除。", "xpack.securitySolution.exceptions.showCommentsLabel": "显示 ({comments} 个) {comments, plural, other {注释}}", - "xpack.securitySolution.exceptions.utilityNumberExceptionsLabel": "正在显示 {items} 个{items, plural, other {例外}}", - "xpack.securitySolution.exceptions.viewer.exceptionDetectionDetailsDescription": "此规则的所有例外将应用到检测规则,而非终端。查看{ruleSettings}以了解详情。", - "xpack.securitySolution.exceptions.viewer.exceptionEndpointDetailsDescription": "此规则的所有例外将应用到终端和检测规则。查看{ruleSettings}以了解详情。", "xpack.securitySolution.fieldBrowser.descriptionForScreenReaderOnly": "{field} 字段的描述:", "xpack.securitySolution.footer.autoRefreshActiveTooltip": "自动刷新已启用时,时间线将显示匹配查询的最近 {numberOfItems} 个事件。", "xpack.securitySolution.formattedNumber.countsLabel": "{mantissa}{scale}{hasRemainder}", @@ -28034,16 +28029,12 @@ "xpack.securitySolution.exceptions.addException.operatingSystemPlaceHolder": "选择操作系统", "xpack.securitySolution.exceptions.addException.sequenceWarning": "此规则的查询包含 EQL 序列语句。创建的例外将应用于序列中的所有事件。", "xpack.securitySolution.exceptions.addException.success": "已成功添加例外", - "xpack.securitySolution.exceptions.andDescription": "且", "xpack.securitySolution.exceptions.badge.readOnly.tooltip": "无法创建、编辑或删除例外", "xpack.securitySolution.exceptions.cancelLabel": "取消", "xpack.securitySolution.exceptions.clearExceptionsLabel": "移除例外列表", "xpack.securitySolution.exceptions.commentEventLabel": "已添加注释", - "xpack.securitySolution.exceptions.commentLabel": "注释", - "xpack.securitySolution.exceptions.descriptionLabel": "描述", - "xpack.securitySolution.exceptions.detectionListLabel": "检测列表", "xpack.securitySolution.exceptions.dissasociateExceptionListError": "无法移除例外列表", - "xpack.securitySolution.exceptions.editButtonLabel": "编辑", + "xpack.securitySolution.exceptions.dissasociateListSuccessText": "例外列表 ({id}) 已成功移除", "xpack.securitySolution.exceptions.editException.bulkCloseLabel": "关闭所有与此例外匹配且根据此规则生成的告警", "xpack.securitySolution.exceptions.editException.bulkCloseLabel.disabled": "关闭所有与此例外匹配且根据此规则生成的告警(不支持列表和非 ECS 字段)", "xpack.securitySolution.exceptions.editException.cancel": "取消", @@ -28056,8 +28047,11 @@ "xpack.securitySolution.exceptions.editException.success": "已成功更新例外", "xpack.securitySolution.exceptions.editException.versionConflictDescription": "此例外可能自您首次选择编辑后已更新。尝试单击“取消”,重新编辑该例外。", "xpack.securitySolution.exceptions.editException.versionConflictTitle": "抱歉,有错误", - "xpack.securitySolution.exceptions.endpointListLabel": "终端列表", "xpack.securitySolution.exceptions.errorLabel": "错误", + "xpack.securitySolution.exceptions.failedLoadPolicies": "加载策略时出错:“{error}”", + "xpack.securitySolution.exceptions.fetch404Error": "关联的例外列表 ({listId}) 已不存在。请移除缺少的例外列表,以将其他例外添加到检测规则。", + "xpack.securitySolution.exceptions.fetchError": "提取例外列表时出错", + "xpack.securitySolution.exceptions.hideCommentsLabel": "隐藏 ({comments}) 个{comments, plural, other {注释}}", "xpack.securitySolution.exceptions.exceptionItem.conditions.and": "且", "xpack.securitySolution.exceptions.exceptionItem.conditions.existsOperator": "存在", "xpack.securitySolution.exceptions.exceptionItem.conditions.existsOperator.not": "不存在", @@ -28080,37 +28074,21 @@ "xpack.securitySolution.exceptions.exceptionItem.metaDetailsBy": "依据", "xpack.securitySolution.exceptions.exceptionItem.updatedLabel": "已更新", "xpack.securitySolution.exceptions.fetchError": "提取例外列表时出错", - "xpack.securitySolution.exceptions.fieldDescription": "字段", "xpack.securitySolution.exceptions.modalErrorAccordionText": "显示规则引用信息:", - "xpack.securitySolution.exceptions.nameLabel": "名称", "xpack.securitySolution.exceptions.operatingSystemFullLabel": "操作系统", "xpack.securitySolution.exceptions.operatingSystemLinux": "Linux", "xpack.securitySolution.exceptions.operatingSystemMac": "macOS", "xpack.securitySolution.exceptions.operatingSystemWindows": "Windows", "xpack.securitySolution.exceptions.operatingSystemWindowsAndMac": "Windows 和 macOS", - "xpack.securitySolution.exceptions.operatorDescription": "运算符", - "xpack.securitySolution.exceptions.orDescription": "OR", "xpack.securitySolution.exceptions.referenceModalCancelButton": "取消", "xpack.securitySolution.exceptions.referenceModalDeleteButton": "移除例外列表", "xpack.securitySolution.exceptions.referenceModalTitle": "移除例外列表", - "xpack.securitySolution.exceptions.removeButtonLabel": "移除", "xpack.securitySolution.exceptions.searchPlaceholder": "例如,示例列表名称", - "xpack.securitySolution.exceptions.utilityRefreshLabel": "刷新", - "xpack.securitySolution.exceptions.valueDescription": "值", + "xpack.securitySolution.exceptions.showCommentsLabel": "显示 ({comments} 个) {comments, plural, other {注释}}", "xpack.securitySolution.exceptions.viewer.addCommentPlaceholder": "添加新注释......", - "xpack.securitySolution.exceptions.viewer.addExceptionLabel": "添加新例外", "xpack.securitySolution.exceptions.viewer.addToClipboard": "注释", "xpack.securitySolution.exceptions.viewer.addToDetectionsListLabel": "添加规则例外", "xpack.securitySolution.exceptions.viewer.addToEndpointListLabel": "添加终端例外", - "xpack.securitySolution.exceptions.viewer.deleteExceptionError": "删除例外时出错", - "xpack.securitySolution.exceptions.viewer.emptyPromptBody": "可以添加例外以微调规则,以便在满足例外条件时不创建检测告警。例外提升检测精确性,从而可以减少误报数。", - "xpack.securitySolution.exceptions.viewer.emptyPromptTitle": "此规则没有例外", - "xpack.securitySolution.exceptions.viewer.exceptionDetectionDetailsDescription.ruleSettingsLink": "规则设置", - "xpack.securitySolution.exceptions.viewer.exceptionEndpointDetailsDescription.ruleSettingsLink": "规则设置", - "xpack.securitySolution.exceptions.viewer.fetchingListError": "提取例外时出错", - "xpack.securitySolution.exceptions.viewer.fetchTotalsError": "获取例外项总数时出错", - "xpack.securitySolution.exceptions.viewer.noSearchResultsPromptBody": "找不到搜索结果。", - "xpack.securitySolution.exceptions.viewer.searchDefaultPlaceholder": "搜索字段(例如:host.name)", "xpack.securitySolution.exitFullScreenButton": "退出全屏", "xpack.securitySolution.expandedValue.hideTopValues.HideTopValues": "隐藏排名最前值", "xpack.securitySolution.expandedValue.links.expandIpDetails": "展开 IP 详情", 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 770a939620b9ba..5f2dcfcb5ff625 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/app.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/app.tsx @@ -73,7 +73,7 @@ export const renderApp = (deps: TriggersAndActionsUiServices) => { export const App = ({ deps }: { deps: TriggersAndActionsUiServices }) => { const { dataViews, uiSettings, theme$ } = deps; - const sections: Section[] = ['rules', 'connectors', 'alerts']; + const sections: Section[] = ['rules', 'connectors', 'logs', 'alerts']; const isDarkMode = useObservable(uiSettings.get$('theme:darkMode')); const sectionsRegex = sections.join('|'); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/constants/index.ts b/x-pack/plugins/triggers_actions_ui/public/application/constants/index.ts index 0792f6703efb45..64bd67989cfbfa 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/constants/index.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/constants/index.ts @@ -13,11 +13,12 @@ export { } from '@kbn/alerting-plugin/common'; export { BASE_ACTION_API_PATH, INTERNAL_BASE_ACTION_API_PATH } from '@kbn/actions-plugin/common'; -export type Section = 'connectors' | 'rules' | 'alerts'; +export type Section = 'connectors' | 'rules' | 'alerts' | 'logs'; export const routeToHome = `/`; export const routeToConnectors = `/connectors`; export const routeToRules = `/rules`; +export const routeToLogs = `/logs`; export const routeToRuleDetails = `/rule/:ruleId`; export const routeToInternalAlerts = `/alerts`; export const legacyRouteToRules = `/alerts`; @@ -41,6 +42,8 @@ export const DEFAULT_SEARCH_PAGE_SIZE: number = 10; export const DEFAULT_RULE_INTERVAL = '1m'; export const RULE_EXECUTION_LOG_COLUMN_IDS = [ + 'rule_id', + 'rule_name', 'id', 'timestamp', 'execution_duration', @@ -73,6 +76,7 @@ export const RULE_EXECUTION_LOG_ALERT_COUNT_COLUMNS = [ ]; export const LOCKED_COLUMNS = [ + 'rule_name', 'timestamp', 'execution_duration', 'status', @@ -81,4 +85,5 @@ export const LOCKED_COLUMNS = [ 'num_errored_actions', ]; -export const RULE_EXECUTION_DEFAULT_INITIAL_VISIBLE_COLUMNS = [...LOCKED_COLUMNS]; +export const RULE_EXECUTION_DEFAULT_INITIAL_VISIBLE_COLUMNS = [...LOCKED_COLUMNS.slice(1)]; +export const GLOBAL_EXECUTION_DEFAULT_INITIAL_VISIBLE_COLUMNS = ['rule_name', ...LOCKED_COLUMNS]; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/home.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/home.test.tsx index 6236e9e2d3d271..0024fef8ac125d 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/home.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/home.test.tsx @@ -70,7 +70,7 @@ describe('home', () => { let home = mountWithIntl(); // Just rules/connectors - expect(home.find('.euiTab__content').length).toBe(2); + expect(home.find('.euiTab__content').length).toBe(3); (getIsExperimentalFeatureEnabled as jest.Mock).mockImplementation((feature: string) => { if (feature === 'internalAlertsTable') { @@ -81,6 +81,6 @@ describe('home', () => { home = mountWithIntl(); // alerts now too! - expect(home.find('.euiTab__content').length).toBe(3); + expect(home.find('.euiTab__content').length).toBe(4); }); }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/home.tsx b/x-pack/plugins/triggers_actions_ui/public/application/home.tsx index 9110ebe1f51c83..8963e63eb44fca 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/home.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/home.tsx @@ -11,7 +11,13 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { EuiSpacer, EuiButtonEmpty, EuiPageHeader } from '@elastic/eui'; import { getIsExperimentalFeatureEnabled } from '../common/get_experimental_features'; -import { Section, routeToConnectors, routeToRules, routeToInternalAlerts } from './constants'; +import { + Section, + routeToConnectors, + routeToRules, + routeToInternalAlerts, + routeToLogs, +} from './constants'; import { getAlertingSectionBreadcrumb } from './lib/breadcrumb'; import { getCurrentDocTitle } from './lib/doc_title'; import { hasShowActionsCapability } from './lib/capabilities'; @@ -25,6 +31,7 @@ const ActionsConnectorsList = lazy( () => import('./sections/actions_connectors_list/components/actions_connectors_list') ); const RulesList = lazy(() => import('./sections/rules_list/components/rules_list')); +const LogsList = lazy(() => import('./sections/logs_list/components/logs_list')); const AlertsPage = lazy(() => import('./sections/alerts_table/alerts_page')); export interface MatchParams { @@ -71,6 +78,11 @@ export const TriggersActionsUIHome: React.FunctionComponent, + }); + if (isInternalAlertsTableEnabled) { tabs.push({ id: 'alerts', @@ -138,6 +150,11 @@ export const TriggersActionsUIHome: React.FunctionComponent + {canShowActions && ( ; + export const loadExecutionLogAggregations = async ({ id, http, @@ -106,3 +108,35 @@ export const loadExecutionLogAggregations = async ({ return rewriteBodyRes(result); }; + +export const loadGlobalExecutionLogAggregations = async ({ + http, + dateStart, + dateEnd, + outcomeFilter, + message, + perPage = 10, + page = 0, + sort = [], +}: LoadGlobalExecutionLogAggregationsProps & { http: HttpSetup }) => { + const sortField: any[] = sort; + const filter = getFilter({ outcomeFilter, message }); + + const result = await http.get>( + `${INTERNAL_BASE_ALERTING_API_PATH}/_global_execution_logs`, + { + query: { + date_start: dateStart, + date_end: dateEnd, + filter: filter.length ? filter.join(' and ') : undefined, + per_page: perPage, + // Need to add the + 1 for pages because APIs are 1 indexed, + // whereas data grid sorts are 0 indexed. + page: page + 1, + sort: sortField.length ? JSON.stringify(sortField) : undefined, + }, + } + ); + + return rewriteBodyRes(result); +}; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/common/components/with_bulk_rule_api_operations.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/common/components/with_bulk_rule_api_operations.tsx index f83cffae60c68f..54e273c4891002 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/common/components/with_bulk_rule_api_operations.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/common/components/with_bulk_rule_api_operations.tsx @@ -36,7 +36,9 @@ import { alertingFrameworkHealth, resolveRule, loadExecutionLogAggregations, + loadGlobalExecutionLogAggregations, LoadExecutionLogAggregationsProps, + LoadGlobalExecutionLogAggregationsProps, loadActionErrorLog, LoadActionErrorLogProps, snoozeRule, @@ -70,6 +72,9 @@ export interface ComponentOpts { loadExecutionLogAggregations: ( props: LoadExecutionLogAggregationsProps ) => Promise; + loadGlobalExecutionLogAggregations: ( + props: LoadGlobalExecutionLogAggregationsProps + ) => Promise; loadActionErrorLog: (props: LoadActionErrorLogProps) => Promise; getHealth: () => Promise; resolveRule: (id: Rule['id']) => Promise; @@ -151,6 +156,14 @@ export function withBulkRuleOperations( http, }) } + loadGlobalExecutionLogAggregations={async ( + loadProps: LoadGlobalExecutionLogAggregationsProps + ) => + loadGlobalExecutionLogAggregations({ + ...loadProps, + http, + }) + } loadActionErrorLog={async (loadProps: LoadActionErrorLogProps) => loadActionErrorLog({ ...loadProps, diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/logs_list/components/logs_list.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/logs_list/components/logs_list.tsx new file mode 100644 index 00000000000000..79e617ee05a494 --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/logs_list/components/logs_list.tsx @@ -0,0 +1,28 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { suspendedComponentWithProps } from '../../../lib/suspended_component_with_props'; +import { RuleEventLogListTableWithApi } from '../../rule_details/components/rule_event_log_list_table'; + +const GLOBAL_EVENT_LOG_LIST_STORAGE_KEY = + 'xpack.triggersActionsUI.globalEventLogList.initialColumns'; + +export const LogsList = () => { + return suspendedComponentWithProps( + RuleEventLogListTableWithApi, + 'xl' + )({ + ruleId: '*', + refreshToken: 0, + initialPageSize: 50, + hasRuleNames: true, + localStorageKey: GLOBAL_EVENT_LOG_LIST_STORAGE_KEY, + }); +}; + +// eslint-disable-next-line import/no-default-export +export default LogsList; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule.tsx index cac3aabad076bd..5c44b9161b2c28 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule.tsx @@ -31,7 +31,7 @@ import { getIsExperimentalFeatureEnabled } from '../../../../common/get_experime import { suspendedComponentWithProps } from '../../../lib/suspended_component_with_props'; import RuleStatusPanelWithApi from './rule_status_panel'; -const RuleEventLogListWithApi = lazy(() => import('./rule_event_log_list')); +const RuleEventLogList = lazy(() => import('./rule_event_log_list')); const RuleAlertList = lazy(() => import('./rule_alert_list')); const RuleDefinition = lazy(() => import('./rule_definition')); @@ -104,11 +104,11 @@ export function RuleComponent({ }), 'data-test-subj': 'eventLogListTab', content: suspendedComponentWithProps>( - RuleEventLogListWithApi, + RuleEventLogList, 'xl' )({ fetchRuleSummary: false, - rule, + ruleId: rule.id, ruleType, ruleSummary, numberOfExecutions, diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_action_error_log_flyout.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_action_error_log_flyout.test.tsx index 5939209bdf591f..dee90d8ceb9f01 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_action_error_log_flyout.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_action_error_log_flyout.test.tsx @@ -11,7 +11,6 @@ import { act } from 'react-dom/test-utils'; import { mountWithIntl, nextTick } from '@kbn/test-jest-helpers'; import { RuleActionErrorLogFlyout } from './rule_action_error_log_flyout'; import { loadActionErrorLog } from '../../../lib/rule_api/load_action_error_log'; -import { Rule } from '../../../../types'; jest.mock('../../../lib/rule_api/load_action_error_log', () => ({ loadActionErrorLog: jest.fn(), @@ -43,33 +42,9 @@ const mockErrorLogResponse = { ], }; -const mockRule: Rule = { - id: uuid.v4(), - enabled: true, - name: `rule-${uuid.v4()}`, - tags: [], - ruleTypeId: '.noop', - consumer: 'consumer', - schedule: { interval: '1m' }, - actions: [], - params: {}, - createdBy: null, - updatedBy: null, - createdAt: new Date(), - updatedAt: new Date(), - apiKeyOwner: null, - throttle: null, - notifyWhen: null, - muteAll: false, - mutedInstanceIds: [], - executionStatus: { - status: 'unknown', - lastExecutionDate: new Date('2020-08-20T19:23:38Z'), - }, -}; - const mockExecution: any = { id: uuid.v4(), + rule_id: uuid.v4(), timestamp: '2022-03-20T07:40:44-07:00', duration: 5000000, status: 'success', @@ -98,7 +73,7 @@ describe('rule_action_error_log_flyout', () => { it('renders correctly', async () => { const wrapper = mountWithIntl( - + ); await act(async () => { @@ -115,7 +90,7 @@ describe('rule_action_error_log_flyout', () => { it('can close the flyout', async () => { const wrapper = mountWithIntl( - + ); await act(async () => { @@ -130,7 +105,7 @@ describe('rule_action_error_log_flyout', () => { it('switches between push and overlay flyout depending on the size of the screen', async () => { const wrapper = mountWithIntl( - + ); await act(async () => { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_action_error_log_flyout.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_action_error_log_flyout.tsx index 3cf361008dbc4f..8c46e3574560c7 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_action_error_log_flyout.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_action_error_log_flyout.tsx @@ -21,23 +21,21 @@ import { useEuiTheme, } from '@elastic/eui'; import { IExecutionLog } from '@kbn/alerting-plugin/common'; -import { Rule } from '../../../../types'; import { RuleErrorLogWithApi } from './rule_error_log'; import { RuleActionErrorBadge } from './rule_action_error_badge'; export interface RuleActionErrorLogFlyoutProps { - rule: Rule; runLog: IExecutionLog; refreshToken?: number; onClose: () => void; } export const RuleActionErrorLogFlyout = (props: RuleActionErrorLogFlyoutProps) => { - const { rule, runLog, refreshToken, onClose } = props; + const { runLog, refreshToken, onClose } = props; const { euiTheme } = useEuiTheme(); - const { id, message, num_errored_actions: totalErrors } = runLog; + const { id, rule_id: ruleId, message, num_errored_actions: totalErrors } = runLog; const isFlyoutPush = useIsWithinBreakpoints(['xl']); @@ -84,7 +82,7 @@ export const RuleActionErrorLogFlyout = (props: RuleActionErrorLogFlyoutProps) = }} />
- + diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_error_log.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_error_log.test.tsx index ac27cab92b1fa6..4ce6b4be05ade3 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_error_log.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_error_log.test.tsx @@ -141,7 +141,7 @@ describe('rule_error_log', () => { it('renders correctly', async () => { const nowMock = jest.spyOn(Date, 'now').mockReturnValue(0); const wrapper = mountWithIntl( - + ); // No data initially @@ -184,7 +184,7 @@ describe('rule_error_log', () => { const nowMock = jest.spyOn(Date, 'now').mockReturnValue(0); const wrapper = mountWithIntl( - + ); await act(async () => { @@ -233,7 +233,7 @@ describe('rule_error_log', () => { }); const wrapper = mountWithIntl( - + ); await act(async () => { @@ -280,7 +280,7 @@ describe('rule_error_log', () => { const nowMock = jest.spyOn(Date, 'now').mockReturnValue(0); const wrapper = mountWithIntl( - + ); await act(async () => { @@ -328,7 +328,7 @@ describe('rule_error_log', () => { it('does not show the refine search prompt normally', async () => { const wrapper = mountWithIntl( - + ); await act(async () => { @@ -346,7 +346,7 @@ describe('rule_error_log', () => { }); const wrapper = mountWithIntl( - + ); await act(async () => { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_error_log.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_error_log.tsx index aeed7c0f8261b0..7c14b17f8d12bc 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_error_log.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_error_log.tsx @@ -25,7 +25,6 @@ import { IExecutionErrors } from '@kbn/alerting-plugin/common'; import { useKibana } from '../../../../common/lib/kibana'; import { RefineSearchPrompt } from '../refine_search_prompt'; -import { Rule } from '../../../../types'; import { ComponentOpts as RuleApis, withBulkRuleOperations, @@ -61,14 +60,14 @@ const updateButtonProps = { const MAX_RESULTS = 1000; export type RuleErrorLogProps = { - rule: Rule; + ruleId: string; runId?: string; refreshToken?: number; requestRefresh?: () => Promise; } & Pick; export const RuleErrorLog = (props: RuleErrorLogProps) => { - const { rule, runId, loadActionErrorLog, refreshToken } = props; + const { ruleId, runId, loadActionErrorLog, refreshToken } = props; const { uiSettings, notifications } = useKibana().services; @@ -131,7 +130,7 @@ export const RuleErrorLog = (props: RuleErrorLogProps) => { setIsLoading(true); try { const result = await loadActionErrorLog({ - id: rule.id, + id: ruleId, runId, message: searchText, dateStart: getParsedDate(dateStart), diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_data_grid.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_data_grid.tsx index 5145b1aa2cd65f..0f6dcc13b1667c 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_data_grid.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_data_grid.tsx @@ -59,6 +59,7 @@ export interface RuleEventLogDataGrid { dateFormat: string; pageSizeOptions?: number[]; selectedRunLog?: IExecutionLog; + showRuleNameAndIdColumns?: boolean; onChangeItemsPerPage: (pageSize: number) => void; onChangePage: (pageIndex: number) => void; onFilterChange: (filter: string[]) => void; @@ -160,6 +161,7 @@ export const RuleEventLogDataGrid = (props: RuleEventLogDataGrid) => { dateFormat, visibleColumns, selectedRunLog, + showRuleNameAndIdColumns = false, setVisibleColumns, setSortingColumns, onChangeItemsPerPage, @@ -180,6 +182,39 @@ export const RuleEventLogDataGrid = (props: RuleEventLogDataGrid) => { const columns: EuiDataGridColumn[] = useMemo( () => [ + ...(showRuleNameAndIdColumns + ? [ + { + id: 'rule_id', + displayAsText: i18n.translate( + 'xpack.triggersActionsUI.sections.ruleDetails.eventLogColumn.ruleId', + { + defaultMessage: 'Rule Id', + } + ), + isSortable: getIsColumnSortable('rule_id'), + actions: { + showSortAsc: false, + showSortDesc: false, + }, + }, + { + id: 'rule_name', + displayAsText: i18n.translate( + 'xpack.triggersActionsUI.sections.ruleDetails.eventLogColumn.ruleName', + { + defaultMessage: 'Rule', + } + ), + isSortable: getIsColumnSortable('rule_name'), + actions: { + showSortAsc: false, + showSortDesc: false, + showHide: false, + }, + }, + ] + : []), { id: 'id', displayAsText: i18n.translate( @@ -394,7 +429,7 @@ export const RuleEventLogDataGrid = (props: RuleEventLogDataGrid) => { isSortable: getIsColumnSortable('timed_out'), }, ], - [getPaginatedRowIndex, onFlyoutOpen, onFilterChange, logs] + [getPaginatedRowIndex, onFlyoutOpen, onFilterChange, showRuleNameAndIdColumns, logs] ); const columnVisibilityProps = useMemo( @@ -524,6 +559,7 @@ export const RuleEventLogDataGrid = (props: RuleEventLogDataGrid) => { const value = logs[pagedRowIndex]?.[columnId as keyof IExecutionLog] as string; const actionErrors = logs[pagedRowIndex]?.num_errored_actions || (0 as number); const version = logs?.[pagedRowIndex]?.version; + const ruleId = runLog?.rule_id; if (columnId === 'num_errored_actions' && runLog) { return ( @@ -555,6 +591,7 @@ export const RuleEventLogDataGrid = (props: RuleEventLogDataGrid) => { value={value} version={version} dateFormat={dateFormat} + ruleId={ruleId} /> diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_list.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_list.test.tsx index 826c208b664987..541cf94d1d5399 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_list.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_list.test.tsx @@ -15,7 +15,10 @@ import { EuiSuperDatePicker, EuiDataGrid } from '@elastic/eui'; import { RuleEventLogListStatusFilter } from './rule_event_log_list_status_filter'; import { RuleEventLogList } from './rule_event_log_list'; import { RefineSearchPrompt } from '../refine_search_prompt'; -import { RULE_EXECUTION_DEFAULT_INITIAL_VISIBLE_COLUMNS } from '../../../constants'; +import { + RULE_EXECUTION_DEFAULT_INITIAL_VISIBLE_COLUMNS, + GLOBAL_EXECUTION_DEFAULT_INITIAL_VISIBLE_COLUMNS, +} from '../../../constants'; import { mockRule, mockRuleType, mockRuleSummary } from './test_helpers'; import { RuleType } from '../../../../types'; import { loadActionErrorLog } from '../../../lib/rule_api/load_action_error_log'; @@ -161,7 +164,7 @@ describe.skip('rule_event_log_list', () => { it('renders correctly', async () => { const wrapper = mountWithIntl( { it('can sort by single and/or multiple column(s)', async () => { const wrapper = mountWithIntl( { it('can filter by execution log outcome status', async () => { const wrapper = mountWithIntl( { const wrapper = mountWithIntl( { const wrapper = mountWithIntl( { it('can save display columns to localStorage', async () => { const wrapper = mountWithIntl( { JSON.parse( localStorage.getItem('xpack.triggersActionsUI.ruleEventLogList.initialColumns') ?? 'null' ) - ).toEqual(RULE_EXECUTION_DEFAULT_INITIAL_VISIBLE_COLUMNS); + ).toEqual(GLOBAL_EXECUTION_DEFAULT_INITIAL_VISIBLE_COLUMNS); wrapper.find('[data-test-subj="dataGridColumnSelectorButton"] button').simulate('click'); @@ -535,7 +538,7 @@ describe.skip('rule_event_log_list', () => { it('does not show the refine search prompt normally', async () => { const wrapper = mountWithIntl( { const wrapper = mountWithIntl( { const wrapper = mountWithIntl( { const wrapper = mountWithIntl( { const wrapper = mountWithIntl( { const wrapper = mountWithIntl( { const wrapper = mountWithIntl( { const wrapper = mountWithIntl( { const wrapper = mountWithIntl( { - if (date.includes('now')) { - return datemath.parse(date)?.format() || date; - } - return date; -}; - -const API_FAILED_MESSAGE = i18n.translate( - 'xpack.triggersActionsUI.sections.ruleDetails.eventLogColumn.apiError', - { - defaultMessage: 'Failed to fetch execution history', - } -); - -const SEARCH_PLACEHOLDER = i18n.translate( - 'xpack.triggersActionsUI.sections.ruleDetails.eventLogColumn.searchPlaceholder', - { - defaultMessage: 'Search event log message', - } -); +import { RuleSummary, RuleType } from '../../../../types'; +import { ComponentOpts as RuleApis } from '../../common/components/with_bulk_rule_api_operations'; +import { RuleEventLogListTableWithApi } from './rule_event_log_list_table'; const RULE_EVENT_LOG_LIST_STORAGE_KEY = 'xpack.triggersActionsUI.ruleEventLogList.initialColumns'; -const getDefaultColumns = (columns: string[]) => { - const columnsWithoutLockedColumn = columns.filter((column) => !LOCKED_COLUMNS.includes(column)); - return [...LOCKED_COLUMNS, ...columnsWithoutLockedColumn]; -}; - -const updateButtonProps = { - iconOnly: true, - fill: false, -}; - -const MAX_RESULTS = 1000; - const ruleEventListContainerStyle = { minHeight: 400 }; export type RuleEventLogListOptions = 'stackManagement' | 'default'; export interface RuleEventLogListCommonProps { - rule: Rule; + ruleId: string; ruleType: RuleType; localStorageKey?: string; refreshToken?: number; requestRefresh?: () => Promise; loadExecutionLogAggregations?: RuleApis['loadExecutionLogAggregations']; fetchRuleSummary?: boolean; + hideChart?: boolean; } export interface RuleEventLogListStackManagementProps { @@ -103,7 +48,7 @@ export const RuleEventLogList = ( props: RuleEventLogListProps ) => { const { - rule, + ruleId, ruleType, localStorageKey = RULE_EVENT_LOG_LIST_STORAGE_KEY, refreshToken, @@ -118,228 +63,11 @@ export const RuleEventLogList = ( onChangeDuration, isLoadingRuleSummary = false, } = props as RuleEventLogListStackManagementProps; - - const { uiSettings, notifications } = useKibana().services; - - const [searchText, setSearchText] = useState(''); - const [search, setSearch] = useState(''); - const [isFlyoutOpen, setIsFlyoutOpen] = useState(false); - const [selectedRunLog, setSelectedRunLog] = useState(); - - // Data grid states - const [logs, setLogs] = useState(); - const [visibleColumns, setVisibleColumns] = useState(() => { - return getDefaultColumns( - JSON.parse(localStorage.getItem(localStorageKey) ?? 'null') || - RULE_EXECUTION_DEFAULT_INITIAL_VISIBLE_COLUMNS - ); - }); - const [sortingColumns, setSortingColumns] = useState([]); - const [filter, setFilter] = useState([]); - const [actualTotalItemCount, setActualTotalItemCount] = useState(0); - const [pagination, setPagination] = useState({ - pageIndex: 0, - pageSize: 10, - totalItemCount: 0, - }); - - // Date related states - const [isLoading, setIsLoading] = useState(false); - const [dateStart, setDateStart] = useState('now-24h'); - const [dateEnd, setDateEnd] = useState('now'); - const [dateFormat] = useState(() => uiSettings?.get('dateFormat')); - const [commonlyUsedRanges] = useState(() => { - return ( - uiSettings - ?.get('timepicker:quickRanges') - ?.map(({ from, to, display }: { from: string; to: string; display: string }) => ({ - start: from, - end: to, - label: display, - })) || [] - ); - }); - - const isInitialized = useRef(false); - - const isOnLastPage = useMemo(() => { - const { pageIndex, pageSize } = pagination; - return (pageIndex + 1) * pageSize >= MAX_RESULTS; - }, [pagination]); - - // Formats the sort columns to be consumed by the API endpoint - const formattedSort = useMemo(() => { - return sortingColumns.map(({ id: sortId, direction }) => ({ - [sortId]: { - order: direction, - }, - })); - }, [sortingColumns]); - - const loadEventLogs = async () => { - if (!loadExecutionLogAggregations) { - return; - } - setIsLoading(true); - try { - const result = await loadExecutionLogAggregations({ - id: rule.id, - sort: formattedSort as LoadExecutionLogAggregationsProps['sort'], - outcomeFilter: filter, - message: searchText, - dateStart: getParsedDate(dateStart), - dateEnd: getParsedDate(dateEnd), - page: pagination.pageIndex, - perPage: pagination.pageSize, - }); - setLogs(result.data); - setPagination({ - ...pagination, - totalItemCount: Math.min(result.total, MAX_RESULTS), - }); - setActualTotalItemCount(result.total); - } catch (e) { - notifications.toasts.addDanger({ - title: API_FAILED_MESSAGE, - text: e.body.message, - }); - } - setIsLoading(false); - }; - - const onChangeItemsPerPage = useCallback( - (pageSize: number) => { - setPagination((prevPagination) => ({ - ...prevPagination, - pageIndex: 0, - pageSize, - })); - }, - [setPagination] - ); - - const onChangePage = useCallback( - (pageIndex: number) => { - setPagination((prevPagination) => ({ - ...prevPagination, - pageIndex, - })); - }, - [setPagination] - ); - - const onTimeChange = useCallback( - ({ start, end, isInvalid }: OnTimeChangeProps) => { - if (isInvalid) { - return; - } - setDateStart(start); - setDateEnd(end); - }, - [setDateStart, setDateEnd] - ); - - const onRefresh = () => { - loadEventLogs(); - }; - - const onFilterChange = useCallback( - (newFilter: string[]) => { - setPagination((prevPagination) => ({ - ...prevPagination, - pageIndex: 0, - })); - setFilter(newFilter); - }, - [setPagination, setFilter] - ); - - const onFlyoutOpen = useCallback((runLog: IExecutionLog) => { - setIsFlyoutOpen(true); - setSelectedRunLog(runLog); - }, []); - - const onFlyoutClose = useCallback(() => { - setIsFlyoutOpen(false); - setSelectedRunLog(undefined); - }, []); - - const onSearchChange = useCallback( - (e) => { - if (e.target.value === '') { - setSearchText(''); - } - setSearch(e.target.value); - }, - [setSearchText, setSearch] - ); - - const onKeyUp = useCallback( - (e) => { - if (e.key === 'Enter') { - setSearchText(search); - } - }, - [search, setSearchText] - ); - - const renderList = () => { - if (!logs) { - return ; - } - return ( - <> - {isLoading && ( - - )} - - - ); - }; - - useEffect(() => { - loadEventLogs(); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [ - sortingColumns, - dateStart, - dateEnd, - filter, - pagination.pageIndex, - pagination.pageSize, - searchText, - ]); - - useEffect(() => { - if (isInitialized.current) { - loadEventLogs(); - } - isInitialized.current = true; - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [refreshToken]); - - useEffect(() => { - localStorage.setItem(localStorageKey, JSON.stringify(visibleColumns)); - }, [localStorageKey, visibleColumns]); - return (
( requestRefresh={requestRefresh} fetchRuleSummary={fetchRuleSummary} /> - - - - - - - - - - - - - {renderList()} - {isOnLastPage && ( - - )} - {isFlyoutOpen && selectedRunLog && ( - - )} +
); }; -export const RuleEventLogListWithApi = withBulkRuleOperations(RuleEventLogList); - // eslint-disable-next-line import/no-default-export -export { RuleEventLogListWithApi as default }; +export { RuleEventLogList as default }; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_list_cell_renderer.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_list_cell_renderer.tsx index 78137d56d70fc1..ebab3489eb7370 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_list_cell_renderer.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_list_cell_renderer.tsx @@ -5,9 +5,12 @@ * 2.0. */ -import React from 'react'; +import React, { useCallback } from 'react'; import moment from 'moment'; import type { EcsEventOutcome } from '@kbn/core/server'; +import { EuiLink } from '@elastic/eui'; +import { useHistory } from 'react-router-dom'; +import { routeToRuleDetails } from '../../../constants'; import { formatRuleAlertCount } from '../../../../common/lib/format_rule_alert_count'; import { RuleEventLogListStatus } from './rule_event_log_list_status'; import { RuleDurationFormat } from '../../rules_list/components/rule_duration_format'; @@ -26,10 +29,17 @@ interface RuleEventLogListCellRendererProps { version?: string; value?: string; dateFormat?: string; + ruleId?: string; } export const RuleEventLogListCellRenderer = (props: RuleEventLogListCellRendererProps) => { - const { columnId, value, version, dateFormat = DEFAULT_DATE_FORMAT } = props; + const { columnId, value, version, dateFormat = DEFAULT_DATE_FORMAT, ruleId } = props; + const history = useHistory(); + + const onClickRuleName = useCallback( + () => ruleId && history.push(routeToRuleDetails.replace(':ruleId', ruleId)), + [ruleId, history] + ); if (typeof value === 'undefined') { return null; @@ -43,6 +53,10 @@ export const RuleEventLogListCellRenderer = (props: RuleEventLogListCellRenderer return <>{moment(value).format(dateFormat)}; } + if (columnId === 'rule_name' && ruleId) { + return {value}; + } + if (RULE_EXECUTION_LOG_ALERT_COUNT_COLUMNS.includes(columnId)) { return <>{formatRuleAlertCount(value, version)}; } diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_list_table.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_list_table.tsx new file mode 100644 index 00000000000000..b647442a8eaf0e --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_list_table.tsx @@ -0,0 +1,396 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useCallback, useEffect, useState, useMemo, useRef } from 'react'; +import { i18n } from '@kbn/i18n'; +import datemath from '@kbn/datemath'; +import { + EuiFieldSearch, + EuiFlexItem, + EuiFlexGroup, + EuiProgress, + EuiSpacer, + EuiDataGridSorting, + Pagination, + EuiSuperDatePicker, + OnTimeChangeProps, +} from '@elastic/eui'; +import { IExecutionLog } from '@kbn/alerting-plugin/common'; +import { useKibana } from '../../../../common/lib/kibana'; +import { + RULE_EXECUTION_DEFAULT_INITIAL_VISIBLE_COLUMNS, + GLOBAL_EXECUTION_DEFAULT_INITIAL_VISIBLE_COLUMNS, + LOCKED_COLUMNS, +} from '../../../constants'; +import { RuleEventLogListStatusFilter } from './rule_event_log_list_status_filter'; +import { RuleEventLogDataGrid } from './rule_event_log_data_grid'; +import { CenterJustifiedSpinner } from '../../../components/center_justified_spinner'; +import { RuleActionErrorLogFlyout } from './rule_action_error_log_flyout'; + +import { RefineSearchPrompt } from '../refine_search_prompt'; +import { LoadExecutionLogAggregationsProps } from '../../../lib/rule_api'; +import { + ComponentOpts as RuleApis, + withBulkRuleOperations, +} from '../../common/components/with_bulk_rule_api_operations'; + +const getParsedDate = (date: string) => { + if (date.includes('now')) { + return datemath.parse(date)?.format() || date; + } + return date; +}; + +const API_FAILED_MESSAGE = i18n.translate( + 'xpack.triggersActionsUI.sections.ruleDetails.eventLogColumn.apiError', + { + defaultMessage: 'Failed to fetch execution history', + } +); + +const SEARCH_PLACEHOLDER = i18n.translate( + 'xpack.triggersActionsUI.sections.ruleDetails.eventLogColumn.searchPlaceholder', + { + defaultMessage: 'Search event log message', + } +); + +const RULE_EVENT_LOG_LIST_STORAGE_KEY = 'xpack.triggersActionsUI.ruleEventLogList.initialColumns'; + +const getDefaultColumns = (columns: string[]) => { + const columnsWithoutLockedColumn = columns.filter((column) => !LOCKED_COLUMNS.includes(column)); + return [...LOCKED_COLUMNS, ...columnsWithoutLockedColumn]; +}; + +const updateButtonProps = { + iconOnly: true, + fill: false, +}; + +const MAX_RESULTS = 1000; + +export type RuleEventLogListOptions = 'stackManagement' | 'default'; + +export type RuleEventLogListCommonProps = { + ruleId: string; + localStorageKey?: string; + refreshToken?: number; + initialPageSize?: number; + // Duplicating these properties is extremely silly but it's the only way to get Jest to cooperate with the way this component is structured + overrideLoadExecutionLogAggregations?: RuleApis['loadExecutionLogAggregations']; + overrideLoadGlobalExecutionLogAggregations?: RuleApis['loadGlobalExecutionLogAggregations']; + hasRuleNames?: boolean; +} & Pick; + +export type RuleEventLogListTableProps = + T extends 'default' + ? RuleEventLogListCommonProps + : T extends 'stackManagement' + ? RuleEventLogListCommonProps + : never; + +export const RuleEventLogListTable = ( + props: RuleEventLogListTableProps +) => { + const { + ruleId, + localStorageKey = RULE_EVENT_LOG_LIST_STORAGE_KEY, + refreshToken, + loadGlobalExecutionLogAggregations, + loadExecutionLogAggregations, + overrideLoadGlobalExecutionLogAggregations, + overrideLoadExecutionLogAggregations, + initialPageSize = 10, + hasRuleNames = false, + } = props; + + const { uiSettings, notifications } = useKibana().services; + + const [searchText, setSearchText] = useState(''); + const [search, setSearch] = useState(''); + const [isFlyoutOpen, setIsFlyoutOpen] = useState(false); + const [selectedRunLog, setSelectedRunLog] = useState(); + + // Data grid states + const [logs, setLogs] = useState(); + const [visibleColumns, setVisibleColumns] = useState(() => { + return getDefaultColumns( + JSON.parse(localStorage.getItem(localStorageKey) ?? 'null') || hasRuleNames + ? GLOBAL_EXECUTION_DEFAULT_INITIAL_VISIBLE_COLUMNS + : RULE_EXECUTION_DEFAULT_INITIAL_VISIBLE_COLUMNS + ); + }); + const [sortingColumns, setSortingColumns] = useState([]); + const [filter, setFilter] = useState([]); + const [actualTotalItemCount, setActualTotalItemCount] = useState(0); + const [pagination, setPagination] = useState({ + pageIndex: 0, + pageSize: initialPageSize, + totalItemCount: 0, + }); + + // Date related states + const [isLoading, setIsLoading] = useState(false); + const [dateStart, setDateStart] = useState('now-24h'); + const [dateEnd, setDateEnd] = useState('now'); + const [dateFormat] = useState(() => uiSettings?.get('dateFormat')); + const [commonlyUsedRanges] = useState(() => { + return ( + uiSettings + ?.get('timepicker:quickRanges') + ?.map(({ from, to, display }: { from: string; to: string; display: string }) => ({ + start: from, + end: to, + label: display, + })) || [] + ); + }); + + const isInitialized = useRef(false); + + const isOnLastPage = useMemo(() => { + const { pageIndex, pageSize } = pagination; + return (pageIndex + 1) * pageSize >= MAX_RESULTS; + }, [pagination]); + + // Formats the sort columns to be consumed by the API endpoint + const formattedSort = useMemo(() => { + return sortingColumns.map(({ id: sortId, direction }) => ({ + [sortId]: { + order: direction, + }, + })); + }, [sortingColumns]); + + const loadLogsFn = useMemo(() => { + if (ruleId === '*') { + return overrideLoadGlobalExecutionLogAggregations ?? loadGlobalExecutionLogAggregations; + } + return overrideLoadExecutionLogAggregations ?? loadExecutionLogAggregations; + }, [ + ruleId, + overrideLoadExecutionLogAggregations, + overrideLoadGlobalExecutionLogAggregations, + loadExecutionLogAggregations, + loadGlobalExecutionLogAggregations, + ]); + + const loadEventLogs = async () => { + if (!loadLogsFn) { + return; + } + setIsLoading(true); + try { + const result = await loadLogsFn({ + id: ruleId, + sort: formattedSort as LoadExecutionLogAggregationsProps['sort'], + outcomeFilter: filter, + message: searchText, + dateStart: getParsedDate(dateStart), + dateEnd: getParsedDate(dateEnd), + page: pagination.pageIndex, + perPage: pagination.pageSize, + }); + setLogs(result.data); + setPagination({ + ...pagination, + totalItemCount: Math.min(result.total, MAX_RESULTS), + }); + setActualTotalItemCount(result.total); + } catch (e) { + notifications.toasts.addDanger({ + title: API_FAILED_MESSAGE, + text: e.body?.message ?? e, + }); + } + setIsLoading(false); + }; + + const onChangeItemsPerPage = useCallback( + (pageSize: number) => { + setPagination((prevPagination) => ({ + ...prevPagination, + pageIndex: 0, + pageSize, + })); + }, + [setPagination] + ); + + const onChangePage = useCallback( + (pageIndex: number) => { + setPagination((prevPagination) => ({ + ...prevPagination, + pageIndex, + })); + }, + [setPagination] + ); + + const onTimeChange = useCallback( + ({ start, end, isInvalid }: OnTimeChangeProps) => { + if (isInvalid) { + return; + } + setDateStart(start); + setDateEnd(end); + }, + [setDateStart, setDateEnd] + ); + + const onRefresh = () => { + loadEventLogs(); + }; + + const onFilterChange = useCallback( + (newFilter: string[]) => { + setPagination((prevPagination) => ({ + ...prevPagination, + pageIndex: 0, + })); + setFilter(newFilter); + }, + [setPagination, setFilter] + ); + + const onFlyoutOpen = useCallback((runLog: IExecutionLog) => { + setIsFlyoutOpen(true); + setSelectedRunLog(runLog); + }, []); + + const onFlyoutClose = useCallback(() => { + setIsFlyoutOpen(false); + setSelectedRunLog(undefined); + }, []); + + const onSearchChange = useCallback( + (e) => { + if (e.target.value === '') { + setSearchText(''); + } + setSearch(e.target.value); + }, + [setSearchText, setSearch] + ); + + const onKeyUp = useCallback( + (e) => { + if (e.key === 'Enter') { + setSearchText(search); + } + }, + [search, setSearchText] + ); + + const renderList = () => { + if (!logs) { + return ; + } + return ( + <> + {isLoading && ( + + )} + + + ); + }; + + useEffect(() => { + loadEventLogs(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [ + sortingColumns, + dateStart, + dateEnd, + filter, + pagination.pageIndex, + pagination.pageSize, + searchText, + ]); + + useEffect(() => { + if (isInitialized.current) { + loadEventLogs(); + } + isInitialized.current = true; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [refreshToken]); + + useEffect(() => { + localStorage.setItem(localStorageKey, JSON.stringify(visibleColumns)); + }, [localStorageKey, visibleColumns]); + + return ( + <> + + + + + + + + + + + + + {renderList()} + {isOnLastPage && ( + + )} + {isFlyoutOpen && selectedRunLog && ( + + )} + + ); +}; + +export const RuleEventLogListTableWithApi = withBulkRuleOperations(RuleEventLogListTable); + +// eslint-disable-next-line import/no-default-export +export { RuleEventLogListTableWithApi as default }; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_execution_summary_and_chart.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_execution_summary_and_chart.test.tsx index ff0ffcc3d67f18..c9626bad07dd62 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_execution_summary_and_chart.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_execution_summary_and_chart.test.tsx @@ -44,7 +44,7 @@ describe('rule_execution_summary_and_chart', () => { it('becomes a stateless component when "fetchRuleSummary" is false', async () => { const wrapper = mountWithIntl( { it('becomes a container component when "fetchRuleSummary" is true', async () => { const wrapper = mountWithIntl( { const wrapper = mountWithIntl( { const { - rule, + ruleId, ruleType, ruleSummary, refreshToken, @@ -103,7 +103,7 @@ export const RuleExecutionSummaryAndChart = (props: RuleExecutionSummaryAndChart } setInternalIsLoadingRuleSummary(true); try { - const loadedSummary = await loadRuleSummary(rule.id, computedNumberOfExecutions); + const loadedSummary = await loadRuleSummary(ruleId, computedNumberOfExecutions); setInternalRuleSummary(loadedSummary); } catch (e) { toasts.addDanger({ @@ -124,7 +124,7 @@ export const RuleExecutionSummaryAndChart = (props: RuleExecutionSummaryAndChart useEffect(() => { getRuleSummary(); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [rule, computedNumberOfExecutions]); + }, [ruleId, computedNumberOfExecutions]); useEffect(() => { if (isInitialized.current) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/global_execution_log.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/global_execution_log.ts new file mode 100644 index 00000000000000..b5dcb9451e854b --- /dev/null +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/global_execution_log.ts @@ -0,0 +1,82 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from '@kbn/expect'; +import { UserAtSpaceScenarios } from '../../../scenarios'; +import { getUrlPrefix, getTestRuleData, ObjectRemover } from '../../../../common/lib'; +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default function globalExecutionLogTests({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + const supertestWithoutAuth = getService('supertestWithoutAuth'); + + const retry = getService('retry'); + + describe('globalExecutionLog', () => { + const objectRemover = new ObjectRemover(supertest); + + after(() => objectRemover.removeAll()); + + it('should return logs only from the current space', async () => { + const startTime = new Date().toISOString(); + + const spaceId = UserAtSpaceScenarios[1].space.id; + const user = UserAtSpaceScenarios[1].user; + const response = await supertest + .post(`${getUrlPrefix(spaceId)}/api/alerting/rule`) + .set('kbn-xsrf', 'foo') + .send( + getTestRuleData({ + rule_type_id: 'test.noop', + schedule: { interval: '1s' }, + throttle: null, + }) + ); + + expect(response.status).to.eql(200); + const alertId = response.body.id; + objectRemover.add(spaceId, alertId, 'rule', 'alerting'); + + const spaceId2 = UserAtSpaceScenarios[4].space.id; + const response2 = await supertest + .post(`${getUrlPrefix(spaceId2)}/api/alerting/rule`) + .set('kbn-xsrf', 'foo') + .send( + getTestRuleData({ + rule_type_id: 'test.noop', + schedule: { interval: '1s' }, + throttle: null, + }) + ); + + expect(response2.status).to.eql(200); + const alertId2 = response2.body.id; + objectRemover.add(spaceId2, alertId2, 'rule', 'alerting'); + + const logs = await retry.try(async () => { + // there can be a successful execute before the error one + const logResponse = await supertestWithoutAuth + .get( + `${getUrlPrefix( + spaceId + )}/internal/alerting/_global_execution_logs?date_start=${startTime}&date_end=9999-12-31T23:59:59Z&per_page=50&page=1` + ) + .set('kbn-xsrf', 'foo') + .auth(user.username, user.password); + expect(logResponse.statusCode).to.be(200); + + return logResponse.body.data; + }); + + // Filter out any excess logs from rules not created by this test + const sanitizedLogs = logs.filter((l: any) => [alertId, alertId2].includes(l.rule_id)); + const allLogsSpace0 = sanitizedLogs.every((l: any) => l.rule_id === alertId); + expect(allLogsSpace0).to.be(true); + }); + }); +} diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/index.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/index.ts index 72890c2bbd90ac..a87a614e9662ad 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/index.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/index.ts @@ -44,6 +44,7 @@ export default function alertingTests({ loadTestFile, getService }: FtrProviderC loadTestFile(require.resolve('./health')); loadTestFile(require.resolve('./excluded')); loadTestFile(require.resolve('./snooze')); + loadTestFile(require.resolve('./global_execution_log')); }); }); } diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/find_rule_exception_references.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/find_rule_exception_references.ts new file mode 100644 index 00000000000000..e75a35d88acc39 --- /dev/null +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/find_rule_exception_references.ts @@ -0,0 +1,184 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from '@kbn/expect'; + +import { DETECTION_ENGINE_RULES_EXCEPTIONS_REFERENCE_URL } from '@kbn/security-solution-plugin/common/constants'; +import { + CreateExceptionListSchema, + ExceptionListTypeEnum, +} from '@kbn/securitysolution-io-ts-list-types'; +import { getCreateExceptionListMinimalSchemaMock } from '@kbn/lists-plugin/common/schemas/request/create_exception_list_schema.mock'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { + createRule, + getSimpleRule, + createSignalsIndex, + deleteSignalsIndex, + deleteAllAlerts, + createExceptionList, +} from '../../utils'; +import { deleteAllExceptions } from '../../../lists_api_integration/utils'; + +// eslint-disable-next-line import/no-default-export +export default ({ getService }: FtrProviderContext) => { + const supertest = getService('supertest'); + const log = getService('log'); + + describe('find_rule_exception_references', () => { + before(async () => { + await createSignalsIndex(supertest, log); + }); + + after(async () => { + await deleteSignalsIndex(supertest, log); + await deleteAllAlerts(supertest, log); + }); + + afterEach(async () => { + await deleteAllExceptions(supertest, log); + }); + + it('returns empty array per list_id if no references are found', async () => { + // create exception list + const newExceptionList: CreateExceptionListSchema = { + ...getCreateExceptionListMinimalSchemaMock(), + list_id: 'i_exist', + namespace_type: 'single', + type: ExceptionListTypeEnum.DETECTION, + }; + const exceptionList = await createExceptionList(supertest, log, newExceptionList); + + // create rule + await createRule(supertest, log, getSimpleRule('rule-1')); + + const { body: references } = await supertest + .get(DETECTION_ENGINE_RULES_EXCEPTIONS_REFERENCE_URL) + .set('kbn-xsrf', 'true') + .query({ + ids: `${exceptionList.id}`, + list_ids: `${exceptionList.list_id}`, + namespace_types: `${exceptionList.namespace_type}`, + }) + .expect(200); + + expect(references).to.eql({ references: [{ i_exist: [] }] }); + }); + + it('returns empty array per list_id if list does not exist', async () => { + // create rule + await createRule(supertest, log, getSimpleRule('rule-1')); + + const { body: references } = await supertest + .get(DETECTION_ENGINE_RULES_EXCEPTIONS_REFERENCE_URL) + .set('kbn-xsrf', 'true') + .query({ + ids: `1234`, + list_ids: `i_dont_exist`, + namespace_types: `single`, + }) + .expect(200); + + expect(references).to.eql({ references: [{ i_dont_exist: [] }] }); + }); + + it('returns found references', async () => { + // create exception list + const newExceptionList: CreateExceptionListSchema = { + ...getCreateExceptionListMinimalSchemaMock(), + list_id: 'i_exist', + namespace_type: 'single', + type: ExceptionListTypeEnum.DETECTION, + }; + const exceptionList = await createExceptionList(supertest, log, newExceptionList); + const exceptionList2 = await createExceptionList(supertest, log, { + ...newExceptionList, + list_id: 'i_exist_2', + }); + + // create rule + const rule = await createRule(supertest, log, { + ...getSimpleRule('rule-2'), + exceptions_list: [ + { + id: `${exceptionList.id}`, + list_id: `${exceptionList.list_id}`, + namespace_type: `${exceptionList.namespace_type}`, + type: `${exceptionList.type}`, + }, + { + id: `${exceptionList2.id}`, + list_id: `${exceptionList2.list_id}`, + namespace_type: `${exceptionList2.namespace_type}`, + type: `${exceptionList2.type}`, + }, + ], + }); + + const { body: references } = await supertest + .get(DETECTION_ENGINE_RULES_EXCEPTIONS_REFERENCE_URL) + .set('kbn-xsrf', 'true') + .query({ + ids: `${exceptionList.id},${exceptionList2.id}`, + list_ids: `${exceptionList.list_id},${exceptionList2.list_id}`, + namespace_types: `${exceptionList.namespace_type},${exceptionList2.namespace_type}`, + }) + .expect(200); + + expect(references).to.eql({ + references: [ + { + i_exist: [ + { + exception_lists: [ + { + id: references.references[0].i_exist[0].exception_lists[0].id, + list_id: 'i_exist', + namespace_type: 'single', + type: 'detection', + }, + { + id: references.references[0].i_exist[0].exception_lists[1].id, + list_id: 'i_exist_2', + namespace_type: 'single', + type: 'detection', + }, + ], + id: rule.id, + name: 'Simple Rule Query', + rule_id: 'rule-2', + }, + ], + }, + { + i_exist_2: [ + { + exception_lists: [ + { + id: references.references[1].i_exist_2[0].exception_lists[0].id, + list_id: 'i_exist', + namespace_type: 'single', + type: 'detection', + }, + { + id: references.references[1].i_exist_2[0].exception_lists[1].id, + list_id: 'i_exist_2', + namespace_type: 'single', + type: 'detection', + }, + ], + id: rule.id, + name: 'Simple Rule Query', + rule_id: 'rule-2', + }, + ], + }, + ], + }); + }); + }); +}; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/index.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/index.ts index 283456df6b1f02..a857757f2d8643 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/index.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/index.ts @@ -31,6 +31,7 @@ export default ({ loadTestFile }: FtrProviderContext): void => { loadTestFile(require.resolve('./delete_rules_bulk')); loadTestFile(require.resolve('./export_rules')); loadTestFile(require.resolve('./find_rules')); + loadTestFile(require.resolve('./find_rule_exception_references')); loadTestFile(require.resolve('./generating_signals')); loadTestFile(require.resolve('./get_prepackaged_rules_status')); loadTestFile(require.resolve('./get_rule_execution_results')); diff --git a/x-pack/test/fleet_api_integration/apis/package_policy/create.ts b/x-pack/test/fleet_api_integration/apis/package_policy/create.ts index aa1c397c1305a6..10b1b709d188fe 100644 --- a/x-pack/test/fleet_api_integration/apis/package_policy/create.ts +++ b/x-pack/test/fleet_api_integration/apis/package_policy/create.ts @@ -445,6 +445,111 @@ export default function (providerContext: FtrProviderContext) { expect(policy.name).to.equal(nameWithWhitespace.trim()); }); + + describe('Simplified package policy', () => { + it('should work with valid values', async () => { + await supertest + .post(`/api/fleet/package_policies`) + .set('kbn-xsrf', 'xxxx') + .send({ + name: `create-simplified-package-policy-required-variables-${Date.now()}`, + description: '', + namespace: 'default', + policy_id: agentPolicyId, + inputs: { + 'with_required_variables-test_input': { + streams: { + 'with_required_variables.log': { + vars: { test_var_required: 'I am required' }, + }, + }, + }, + }, + package: { + name: 'with_required_variables', + version: '0.1.0', + }, + }) + .expect(200); + }); + + it('should throw with invalid variables', async () => { + const { body } = await supertest + .post(`/api/fleet/package_policies`) + .set('kbn-xsrf', 'xxxx') + .send({ + name: `create-simplified-package-policy-required-variables-${Date.now()}`, + description: '', + namespace: 'default', + policy_id: agentPolicyId, + inputs: { + 'with_required_variables-test_input': { + streams: { + 'with_required_variables.log': { + vars: { var_id_do_exists: 'I do not exists' }, + }, + }, + }, + }, + package: { + name: 'with_required_variables', + version: '0.1.0', + }, + }) + .expect(400); + + expect(body.message).eql( + 'Variable with_required_variables-test_input with_required_variables.log:var_id_do_exists not found' + ); + }); + + it('should throw with invalid inputs', async () => { + await supertest + .post(`/api/fleet/package_policies`) + .set('kbn-xsrf', 'xxxx') + .send({ + name: `create-simplified-package-policy-required-variables-${Date.now()}`, + description: '', + namespace: 'default', + policy_id: agentPolicyId, + inputs: { + 'i-do-not-exists-input': {}, + }, + package: { + name: 'with_required_variables', + version: '0.1.0', + }, + }) + .expect(400); + }); + + it('should throw with invalid streams', async () => { + await supertest + .post(`/api/fleet/package_policies`) + .set('kbn-xsrf', 'xxxx') + .send({ + name: `create-simplified-package-policy-required-variables-${Date.now()}`, + description: '', + namespace: 'default', + policy_id: agentPolicyId, + inputs: { + 'with_required_variables-test_input': { + streams: { + 'iamnotexisting.log': { + vars: { test_var_required: 'I am required' }, + }, + }, + }, + }, + package: { + name: 'with_required_variables', + version: '0.1.0', + }, + }) + .expect(400); + }); + }); + describe('Package verification', () => { const uninstallPackage = async (pkg: string, version: string) => { await supertest.delete(`/api/fleet/epm/packages/${pkg}/${version}`).set('kbn-xsrf', 'xxxx'); diff --git a/x-pack/test/fleet_api_integration/apis/package_policy/update.ts b/x-pack/test/fleet_api_integration/apis/package_policy/update.ts index 4c5320f037dd83..8d565728c2d4c7 100644 --- a/x-pack/test/fleet_api_integration/apis/package_policy/update.ts +++ b/x-pack/test/fleet_api_integration/apis/package_policy/update.ts @@ -30,6 +30,7 @@ export default function (providerContext: FtrProviderContext) { let managedAgentPolicyId: string; let packagePolicyId: string; let packagePolicyId2: string; + let packagePolicyId3: string; before(async () => { await kibanaServer.savedObjects.cleanStandardList(); await getService('esArchiver').load( @@ -107,6 +108,30 @@ export default function (providerContext: FtrProviderContext) { }, }); packagePolicyId2 = packagePolicyResponse2.item.id; + + const { body: packagePolicyResponse3 } = await supertest + .post(`/api/fleet/package_policies`) + .set('kbn-xsrf', 'xxxx') + .send({ + name: 'update-package-policy-with_required_variables-1', + description: '', + namespace: 'default', + policy_id: agentPolicyId, + inputs: { + 'with_required_variables-test_input': { + streams: { + 'with_required_variables.log': { + vars: { test_var_required: 'I am required' }, + }, + }, + }, + }, + package: { + name: 'with_required_variables', + version: '0.1.0', + }, + }); + packagePolicyId3 = packagePolicyResponse3.item.id; }); after(async function () { @@ -268,5 +293,54 @@ export default function (providerContext: FtrProviderContext) { }, }); }); + + describe('Simplified package policy', async () => { + it('should work with valid values', async function () { + await supertest + .put(`/api/fleet/package_policies/${packagePolicyId3}`) + .set('kbn-xsrf', 'xxxx') + .send({ + name: `update-simplified-package-policy-with_required_variables-${Date.now()}`, + description: '', + namespace: 'default', + policy_id: agentPolicyId, + inputs: { + 'with_required_variables-test_input': { + streams: { + 'with_required_variables.log': { + vars: { test_var_required: 'I am required' }, + }, + }, + }, + }, + package: { + name: 'with_required_variables', + version: '0.1.0', + }, + }) + .expect(200); + }); + + it('should return a 400 with invalid inputs', async function () { + const { body } = await supertest + .put(`/api/fleet/package_policies/${packagePolicyId3}`) + .set('kbn-xsrf', 'xxxx') + .send({ + name: `update-simplified-package-policy-with_required_variables-${Date.now()}`, + description: '', + namespace: 'default', + policy_id: agentPolicyId, + inputs: { + 'with_required_variables-i-do-not-exists': {}, + }, + package: { + name: 'with_required_variables', + version: '0.1.0', + }, + }) + .expect(400); + expect(body.message).eql('Input not found: with_required_variables-i-do-not-exists'); + }); + }); }); } diff --git a/x-pack/test/functional/apps/lens/group3/annotations.ts b/x-pack/test/functional/apps/lens/group3/annotations.ts index d6197cc2e39ab8..e139677737b426 100644 --- a/x-pack/test/functional/apps/lens/group3/annotations.ts +++ b/x-pack/test/functional/apps/lens/group3/annotations.ts @@ -76,7 +76,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { ) ).to.be(true); await PageObjects.lens.closeDimensionEditor(); - await testSubjects.existOrFail('xyVisAnnotationText'); await testSubjects.existOrFail('xyVisGroupedAnnotationIcon'); }); }); diff --git a/x-pack/test/lists_api_integration/security_and_spaces/tests/find_exception_list_items.ts b/x-pack/test/lists_api_integration/security_and_spaces/tests/find_exception_list_items.ts index bb65b1c9c49337..909930d7134737 100644 --- a/x-pack/test/lists_api_integration/security_and_spaces/tests/find_exception_list_items.ts +++ b/x-pack/test/lists_api_integration/security_and_spaces/tests/find_exception_list_items.ts @@ -9,8 +9,14 @@ import expect from '@kbn/expect'; import { EXCEPTION_LIST_URL, EXCEPTION_LIST_ITEM_URL } from '@kbn/securitysolution-list-constants'; import { getExceptionListItemResponseMockWithoutAutoGeneratedValues } from '@kbn/lists-plugin/common/schemas/response/exception_list_item_schema.mock'; -import { getCreateExceptionListItemMinimalSchemaMock } from '@kbn/lists-plugin/common/schemas/request/create_exception_list_item_schema.mock'; -import { getCreateExceptionListMinimalSchemaMock } from '@kbn/lists-plugin/common/schemas/request/create_exception_list_schema.mock'; +import { + getCreateExceptionListItemMinimalSchemaMock, + getCreateExceptionListItemMinimalSchemaMockWithoutId, +} from '@kbn/lists-plugin/common/schemas/request/create_exception_list_item_schema.mock'; +import { + getCreateExceptionListMinimalSchemaMock, + getCreateExceptionListDetectionSchemaMock, +} from '@kbn/lists-plugin/common/schemas/request/create_exception_list_schema.mock'; import { FtrProviderContext } from '../../common/ftr_provider_context'; import { deleteAllExceptions, removeExceptionListItemServerGeneratedProperties } from '../../utils'; @@ -51,6 +57,79 @@ export default ({ getService }: FtrProviderContext): void => { }); }); + it('should return matching items when search is passed in', async () => { + // create exception list + await supertest + .post(EXCEPTION_LIST_URL) + .set('kbn-xsrf', 'true') + .send(getCreateExceptionListDetectionSchemaMock()) + .expect(200); + + // create exception list items + await supertest + .post(EXCEPTION_LIST_ITEM_URL) + .set('kbn-xsrf', 'true') + .send({ + ...getCreateExceptionListItemMinimalSchemaMockWithoutId(), + list_id: getCreateExceptionListDetectionSchemaMock().list_id, + item_id: '1', + entries: [ + { field: 'host.name', value: 'some host', operator: 'included', type: 'match' }, + ], + }) + .expect(200); + await supertest + .post(EXCEPTION_LIST_ITEM_URL) + .set('kbn-xsrf', 'true') + .send({ + ...getCreateExceptionListItemMinimalSchemaMockWithoutId(), + item_id: '2', + list_id: getCreateExceptionListDetectionSchemaMock().list_id, + entries: [{ field: 'foo', operator: 'included', type: 'exists' }], + }) + .expect(200); + + const { body } = await supertest + .get( + `${EXCEPTION_LIST_ITEM_URL}/_find?list_id=${ + getCreateExceptionListMinimalSchemaMock().list_id + }&namespace_type=single&page=1&per_page=25&search=host&sort_field=exception-list.created_at&sort_order=desc` + ) + .set('kbn-xsrf', 'true') + .send() + .expect(200); + + body.data = [removeExceptionListItemServerGeneratedProperties(body.data[0])]; + expect(body).to.eql({ + data: [ + { + comments: [], + created_by: 'elastic', + description: 'some description', + entries: [ + { + field: 'host.name', + operator: 'included', + type: 'match', + value: 'some host', + }, + ], + item_id: '1', + list_id: 'some-list-id', + name: 'some name', + namespace_type: 'single', + os_types: ['windows'], + tags: [], + type: 'simple', + updated_by: 'elastic', + }, + ], + page: 1, + per_page: 25, + total: 1, + }); + }); + it('should return 404 if given a list_id that does not exist', async () => { const { body } = await supertest .get(`${EXCEPTION_LIST_ITEM_URL}/_find?list_id=non_exist`) diff --git a/x-pack/test/security_solution_cypress/es_archives/exceptions_2/data.json b/x-pack/test/security_solution_cypress/es_archives/exceptions_2/data.json index 3ad636b20a9cc8..72dc01b9bac545 100644 --- a/x-pack/test/security_solution_cypress/es_archives/exceptions_2/data.json +++ b/x-pack/test/security_solution_cypress/es_archives/exceptions_2/data.json @@ -4,7 +4,7 @@ "id": "_aZE5nwBOpWiDweSth_E", "index": "exceptions-0002", "source": { - "@timestamp": "2019-09-02T00:41:06.527Z", + "@timestamp": "2019-09-02T00:45:06.527Z", "agent": { "name": "foo" }, @@ -23,4 +23,31 @@ ] } } -} \ No newline at end of file +} + +{ + "type": "doc", + "value": { + "id": "_aZE5nwBOpWiDweSth_F", + "index": "exceptions-0002", + "source": { + "@timestamp": "2019-09-02T00:46:06.527Z", + "agent": { + "name": "bar" + }, + "unique_value": { + "test": "test field 2" + }, + "user" : [ + { + "name" : "foo", + "id" : "123" + }, + { + "name" : "bar", + "id" : "456" + } + ] + } + } +} diff --git a/yarn.lock b/yarn.lock index 92574a3ec5eb13..40141be799b42f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1478,10 +1478,10 @@ dependencies: object-hash "^1.3.0" -"@elastic/charts@48.0.0": - version "48.0.0" - resolved "https://registry.yarnpkg.com/@elastic/charts/-/charts-48.0.0.tgz#ccbbe7507102f078b80285e045a421105c0fc780" - integrity sha512-sj0L0JKU3KLJw0Ci1RzSj5WkhGc7ptAft/ulunF+w0i5vG7qgDdbnemCvRIPkgGiu2AnAnIj/bkK3IcxpAbmGA== +"@elastic/charts@48.0.1": + version "48.0.1" + resolved "https://registry.yarnpkg.com/@elastic/charts/-/charts-48.0.1.tgz#52391ab37bcc3188748e5ac4ffe5275ce8cd93cd" + integrity sha512-cmu65UTwbQSj4Gk1gdhlORfbqrCeel9FMpz/fVODOpsRWh/4dwxZhN/x9Ob1e4W5jZDfd6OV47Gc9ZfQVzxKrQ== dependencies: "@popperjs/core" "^2.4.0" bezier-easing "^2.1.0" @@ -3219,6 +3219,26 @@ version "0.0.0" uid "" +"@kbn/core-status-common-internal@link:bazel-bin/packages/core/status/core-status-common-internal": + version "0.0.0" + uid "" + +"@kbn/core-status-common@link:bazel-bin/packages/core/status/core-status-common": + version "0.0.0" + uid "" + +"@kbn/core-status-server-internal@link:bazel-bin/packages/core/status/core-status-server-internal": + version "0.0.0" + uid "" + +"@kbn/core-status-server-mocks@link:bazel-bin/packages/core/status/core-status-server-mocks": + version "0.0.0" + uid "" + +"@kbn/core-status-server@link:bazel-bin/packages/core/status/core-status-server": + version "0.0.0" + uid "" + "@kbn/core-test-helpers-deprecations-getters@link:bazel-bin/packages/core/test-helpers/core-test-helpers-deprecations-getters": version "0.0.0" uid "" @@ -3411,14 +3431,6 @@ version "0.0.0" uid "" -"@kbn/jsonc@link:bazel-bin/packages/kbn-jsonc": - version "0.0.0" - uid "" - -"@kbn/kibana-manifest-parser@link:bazel-bin/packages/kbn-kibana-manifest-parser": - version "0.0.0" - uid "" - "@kbn/kibana-manifest-schema@link:bazel-bin/packages/kbn-kibana-manifest-schema": version "0.0.0" uid "" @@ -7321,6 +7333,26 @@ version "0.0.0" uid "" +"@types/kbn__core-status-common-internal@link:bazel-bin/packages/core/status/core-status-common-internal/npm_module_types": + version "0.0.0" + uid "" + +"@types/kbn__core-status-common@link:bazel-bin/packages/core/status/core-status-common/npm_module_types": + version "0.0.0" + uid "" + +"@types/kbn__core-status-server-internal@link:bazel-bin/packages/core/status/core-status-server-internal/npm_module_types": + version "0.0.0" + uid "" + +"@types/kbn__core-status-server-mocks@link:bazel-bin/packages/core/status/core-status-server-mocks/npm_module_types": + version "0.0.0" + uid "" + +"@types/kbn__core-status-server@link:bazel-bin/packages/core/status/core-status-server/npm_module_types": + version "0.0.0" + uid "" + "@types/kbn__core-test-helpers-deprecations-getters@link:bazel-bin/packages/core/test-helpers/core-test-helpers-deprecations-getters/npm_module_types": version "0.0.0" uid "" @@ -7493,18 +7525,10 @@ version "0.0.0" uid "" -"@types/kbn__jsonc@link:bazel-bin/packages/kbn-jsonc/npm_module_types": - version "0.0.0" - uid "" - "@types/kbn__kbn-ci-stats-performance-metrics@link:bazel-bin/packages/kbn-kbn-ci-stats-performance-metrics/npm_module_types": version "0.0.0" uid "" -"@types/kbn__kibana-manifest-parser@link:bazel-bin/packages/kbn-kibana-manifest-parser/npm_module_types": - version "0.0.0" - uid "" - "@types/kbn__kibana-manifest-schema@link:bazel-bin/packages/kbn-kibana-manifest-schema/npm_module_types": version "0.0.0" uid ""