diff --git a/src/plugins/saved_objects_tagging_oss/common/types.ts b/src/plugins/saved_objects_tagging_oss/common/types.ts index 205f6984ed618..db7e71431a09f 100644 --- a/src/plugins/saved_objects_tagging_oss/common/types.ts +++ b/src/plugins/saved_objects_tagging_oss/common/types.ts @@ -23,8 +23,14 @@ export interface GetAllTagsOptions { asSystemRequest?: boolean; } +export interface CreateTagOptions { + id?: string; + overwrite?: boolean; + refresh?: boolean | 'wait_for'; +} + export interface ITagsClient { - create(attributes: TagAttributes): Promise; + create(attributes: TagAttributes, options?: CreateTagOptions): Promise; get(id: string): Promise; getAll(options?: GetAllTagsOptions): Promise; delete(id: string): Promise; diff --git a/x-pack/plugins/fleet/kibana.json b/x-pack/plugins/fleet/kibana.json index 409e9f2a896ae..462e68a097962 100644 --- a/x-pack/plugins/fleet/kibana.json +++ b/x-pack/plugins/fleet/kibana.json @@ -8,7 +8,7 @@ "server": true, "ui": true, "configPath": ["xpack", "fleet"], - "requiredPlugins": ["licensing", "data", "encryptedSavedObjects", "navigation", "customIntegrations", "share", "spaces", "security", "unifiedSearch"], + "requiredPlugins": ["licensing", "data", "encryptedSavedObjects", "navigation", "customIntegrations", "share", "spaces", "security", "unifiedSearch", "savedObjectsTagging"], "optionalPlugins": ["features", "cloud", "usageCollection", "home", "globalSearch", "telemetry", "discover", "ingestPipelines"], "extraPublicDirs": ["common"], "requiredBundles": ["kibanaReact", "cloud", "esUiShared", "infra", "kibanaUtils", "usageCollection", "unifiedSearch"] diff --git a/x-pack/plugins/fleet/server/plugin.ts b/x-pack/plugins/fleet/server/plugin.ts index 824cfb091e2c9..a2e2208d0e8f1 100644 --- a/x-pack/plugins/fleet/server/plugin.ts +++ b/x-pack/plugins/fleet/server/plugin.ts @@ -42,6 +42,8 @@ import type { CloudSetup } from '@kbn/cloud-plugin/server'; import type { SpacesPluginStart } from '@kbn/spaces-plugin/server'; +import type { SavedObjectTaggingStart } from '@kbn/saved-objects-tagging-plugin/server'; + import type { FleetConfigType } from '../common/types'; import type { FleetAuthz } from '../common'; import type { ExperimentalFeatures } from '../common/experimental_features'; @@ -115,6 +117,7 @@ export interface FleetStartDeps { encryptedSavedObjects: EncryptedSavedObjectsPluginStart; security: SecurityPluginStart; telemetry?: TelemetryPluginStart; + savedObjectsTagging: SavedObjectTaggingStart; } export interface FleetAppContext { @@ -128,6 +131,7 @@ export interface FleetAppContext { configInitialValue: FleetConfigType; experimentalFeatures: ExperimentalFeatures; savedObjects: SavedObjectsServiceStart; + savedObjectsTagging?: SavedObjectTaggingStart; isProductionMode: PluginInitializerContext['env']['mode']['prod']; kibanaVersion: PluginInitializerContext['env']['packageInfo']['version']; kibanaBranch: PluginInitializerContext['env']['packageInfo']['branch']; @@ -400,6 +404,7 @@ export class FleetPlugin this.configInitialValue.enableExperimental || [] ), savedObjects: core.savedObjects, + savedObjectsTagging: plugins.savedObjectsTagging, isProductionMode: this.isProductionMode, kibanaVersion: this.kibanaVersion, kibanaBranch: this.kibanaBranch, diff --git a/x-pack/plugins/fleet/server/services/app_context.ts b/x-pack/plugins/fleet/server/services/app_context.ts index da9715d9471f0..86f9408bef3f3 100644 --- a/x-pack/plugins/fleet/server/services/app_context.ts +++ b/x-pack/plugins/fleet/server/services/app_context.ts @@ -26,6 +26,8 @@ import type { SecurityPluginStart, SecurityPluginSetup } from '@kbn/security-plu import type { CloudSetup } from '@kbn/cloud-plugin/server'; +import type { SavedObjectTaggingStart } from '@kbn/saved-objects-tagging-plugin/server'; + import type { FleetConfigType } from '../../common/types'; import type { ExperimentalFeatures } from '../../common/experimental_features'; import type { @@ -58,6 +60,7 @@ class AppContextService { private httpSetup?: HttpServiceSetup; private externalCallbacks: ExternalCallbacksStorage = new Map(); private telemetryEventsSender: TelemetryEventsSender | undefined; + private savedObjectsTagging: SavedObjectTaggingStart | undefined; public start(appContext: FleetAppContext) { this.data = appContext.data; @@ -75,6 +78,7 @@ class AppContextService { this.kibanaBranch = appContext.kibanaBranch; this.httpSetup = appContext.httpSetup; this.telemetryEventsSender = appContext.telemetryEventsSender; + this.savedObjectsTagging = appContext.savedObjectsTagging; if (appContext.config$) { this.config$ = appContext.config$; @@ -143,6 +147,13 @@ class AppContextService { return this.savedObjects; } + public getSavedObjectsTagging() { + if (!this.savedObjectsTagging) { + throw new Error('Saved object tagging start service not set.'); + } + return this.savedObjectsTagging; + } + public getInternalUserSOClient(request: KibanaRequest) { // soClient as kibana internal users, be careful on how you use it, security is not enabled return appContextService.getSavedObjects().getScopedClient(request, { diff --git a/x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts b/x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts index 110fb4535ef92..b4a9564e1199e 100644 --- a/x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts +++ b/x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts @@ -18,6 +18,8 @@ import type { SavedObjectsImportSuccess, SavedObjectsImportFailure } from '@kbn/ import { createListStream } from '@kbn/utils'; import { partition } from 'lodash'; +import type { IAssignmentService, ITagsClient } from '@kbn/saved-objects-tagging-plugin/server'; + import { PACKAGES_SAVED_OBJECT_TYPE } from '../../../../../common'; import { getAsset, getPathParts } from '../../archive'; import { KibanaAssetType, KibanaSavedObjectType } from '../../../../types'; @@ -27,6 +29,10 @@ import { indexPatternTypes, getIndexPatternSavedObjects } from '../index_pattern import { saveKibanaAssetsRefs } from '../../packages/install'; import { deleteKibanaSavedObjectsAssets } from '../../packages/remove'; +import { withPackageSpan } from '../../packages/utils'; + +import { tagKibanaAssets } from './tag_assets'; + type SavedObjectsImporterContract = Pick; const formatImportErrorsForLog = (errors: SavedObjectsImportFailure[]) => JSON.stringify( @@ -128,15 +134,21 @@ export async function installKibanaAssets(options: { export async function installKibanaAssetsAndReferences({ savedObjectsClient, savedObjectsImporter, + savedObjectTagAssignmentService, + savedObjectTagClient, logger, pkgName, + pkgTitle, paths, installedPkg, }: { savedObjectsClient: SavedObjectsClientContract; savedObjectsImporter: Pick; + savedObjectTagAssignmentService: IAssignmentService; + savedObjectTagClient: ITagsClient; logger: Logger; pkgName: string; + pkgTitle: string; paths: string[]; installedPkg?: SavedObject; }) { @@ -156,6 +168,16 @@ export async function installKibanaAssetsAndReferences({ kibanaAssets, }); + await withPackageSpan('Create and assign package tags', () => + tagKibanaAssets({ + savedObjectTagAssignmentService, + savedObjectTagClient, + kibanaAssets, + pkgTitle, + pkgName, + }) + ); + return installedKibanaAssetsRefs; } diff --git a/x-pack/plugins/fleet/server/services/epm/kibana/assets/tag_assets.test.ts b/x-pack/plugins/fleet/server/services/epm/kibana/assets/tag_assets.test.ts new file mode 100644 index 0000000000000..4d3a4e8557a68 --- /dev/null +++ b/x-pack/plugins/fleet/server/services/epm/kibana/assets/tag_assets.test.ts @@ -0,0 +1,127 @@ +/* + * 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 { tagKibanaAssets } from './tag_assets'; + +describe('tagKibanaAssets', () => { + const savedObjectTagAssignmentService = { + updateTagAssignments: jest.fn(), + } as any; + const savedObjectTagClient = { + getAll: jest.fn(), + create: jest.fn(), + } as any; + + beforeEach(() => { + savedObjectTagAssignmentService.updateTagAssignments.mockReset(); + savedObjectTagClient.getAll.mockReset(); + savedObjectTagClient.create.mockReset(); + }); + + it('should create Managed and System tags when tagKibanaAssets with System package', async () => { + savedObjectTagClient.getAll.mockResolvedValue([]); + savedObjectTagClient.create.mockImplementation(({ name }: { name: string }) => + Promise.resolve({ id: name.toLowerCase(), name }) + ); + const kibanaAssets = { dashboard: [{ id: 'dashboard1', type: 'dashboard' }] } as any; + + await tagKibanaAssets({ + savedObjectTagAssignmentService, + savedObjectTagClient, + kibanaAssets, + pkgTitle: 'System', + pkgName: 'system', + }); + + expect(savedObjectTagClient.create).toHaveBeenCalledWith( + { + name: 'Managed', + description: '', + color: '#FFFFFF', + }, + { id: 'managed', overwrite: true, refresh: false } + ); + expect(savedObjectTagClient.create).toHaveBeenCalledWith( + { + name: 'System', + description: '', + color: '#FFFFFF', + }, + { id: 'system', overwrite: true, refresh: false } + ); + expect(savedObjectTagAssignmentService.updateTagAssignments).toHaveBeenCalledWith({ + tags: ['managed', 'system'], + assign: kibanaAssets.dashboard, + unassign: [], + refresh: false, + }); + }); + + it('should only assign Managed and System tags when tags already exist', async () => { + savedObjectTagClient.getAll.mockResolvedValue([ + { id: 'managed', name: 'Managed' }, + { id: 'system', name: 'System' }, + ]); + const kibanaAssets = { dashboard: [{ id: 'dashboard1', type: 'dashboard' }] } as any; + + await tagKibanaAssets({ + savedObjectTagAssignmentService, + savedObjectTagClient, + kibanaAssets, + pkgTitle: 'System', + pkgName: 'system', + }); + + expect(savedObjectTagClient.create).not.toHaveBeenCalled(); + expect(savedObjectTagAssignmentService.updateTagAssignments).toHaveBeenCalledWith({ + tags: ['managed', 'system'], + assign: kibanaAssets.dashboard, + unassign: [], + refresh: false, + }); + }); + + it('should skip non taggable asset types', async () => { + savedObjectTagClient.getAll.mockResolvedValue([]); + savedObjectTagClient.create.mockImplementation(({ name }: { name: string }) => + Promise.resolve({ id: name.toLowerCase(), name }) + ); + const kibanaAssets = { + dashboard: [{ id: 'dashboard1', type: 'dashboard' }], + search: [{ id: 's1', type: 'search' }], + visualization: [{ id: 'v1', type: 'visualization' }], + } as any; + + await tagKibanaAssets({ + savedObjectTagAssignmentService, + savedObjectTagClient, + kibanaAssets, + pkgTitle: 'System', + pkgName: 'system', + }); + + expect(savedObjectTagAssignmentService.updateTagAssignments).toHaveBeenCalledWith({ + tags: ['managed', 'system'], + assign: [...kibanaAssets.dashboard, ...kibanaAssets.visualization], + unassign: [], + refresh: false, + }); + }); + + it('should do nothing if no taggable assets', async () => { + const kibanaAssets = { search: [{ id: 's1', type: 'search' }] } as any; + + await tagKibanaAssets({ + savedObjectTagAssignmentService, + savedObjectTagClient, + kibanaAssets, + pkgTitle: 'System', + pkgName: 'system', + }); + + expect(savedObjectTagAssignmentService.updateTagAssignments).not.toHaveBeenCalled(); + }); +}); diff --git a/x-pack/plugins/fleet/server/services/epm/kibana/assets/tag_assets.ts b/x-pack/plugins/fleet/server/services/epm/kibana/assets/tag_assets.ts new file mode 100644 index 0000000000000..53a6df568a8c0 --- /dev/null +++ b/x-pack/plugins/fleet/server/services/epm/kibana/assets/tag_assets.ts @@ -0,0 +1,80 @@ +/* + * 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 { taggableTypes } from '@kbn/saved-objects-tagging-plugin/common/constants'; +import type { IAssignmentService, ITagsClient } from '@kbn/saved-objects-tagging-plugin/server'; + +import type { KibanaAssetType } from '../../../../../common'; + +import type { ArchiveAsset } from './install'; + +const TAG_COLOR = '#FFFFFF'; +const MANAGED_TAG_NAME = 'Managed'; +const MANAGED_TAG_ID = 'managed'; + +export async function tagKibanaAssets({ + savedObjectTagAssignmentService, + savedObjectTagClient, + kibanaAssets, + pkgTitle, + pkgName, +}: { + savedObjectTagAssignmentService: IAssignmentService; + savedObjectTagClient: ITagsClient; + kibanaAssets: Record; + pkgTitle: string; + pkgName: string; +}) { + const taggableAssets = Object.entries(kibanaAssets).flatMap(([assetType, assets]) => { + if (!taggableTypes.includes(assetType as KibanaAssetType)) { + return []; + } + + if (!assets.length) { + return []; + } + + return assets; + }); + + // no assets to tag + if (taggableAssets.length === 0) { + return; + } + + const allTags = await savedObjectTagClient.getAll(); + let managedTag = allTags.find((tag) => tag.name === MANAGED_TAG_NAME); + if (!managedTag) { + managedTag = await savedObjectTagClient.create( + { + name: MANAGED_TAG_NAME, + description: '', + color: TAG_COLOR, + }, + { id: MANAGED_TAG_ID, overwrite: true, refresh: false } + ); + } + + let packageTag = allTags.find((tag) => tag.name === pkgTitle); + if (!packageTag) { + packageTag = await savedObjectTagClient.create( + { + name: pkgTitle, + description: '', + color: TAG_COLOR, + }, + { id: pkgName, overwrite: true, refresh: false } + ); + } + + await savedObjectTagAssignmentService.updateTagAssignments({ + tags: [managedTag.id, packageTag.id], + assign: taggableAssets, + unassign: [], + refresh: false, + }); +} diff --git a/x-pack/plugins/fleet/server/services/epm/packages/_install_package.ts b/x-pack/plugins/fleet/server/services/epm/packages/_install_package.ts index 35b5f490e538b..00eb71e918bd2 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/_install_package.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/_install_package.ts @@ -14,6 +14,8 @@ import type { } from '@kbn/core/server'; import { SavedObjectsErrorHelpers } from '@kbn/core/server'; +import type { IAssignmentService, ITagsClient } from '@kbn/saved-objects-tagging-plugin/server'; + import { MAX_TIME_COMPLETE_INSTALL, ASSETS_SAVED_OBJECT_TYPE, @@ -56,6 +58,8 @@ import { withPackageSpan } from './utils'; export async function _installPackage({ savedObjectsClient, savedObjectsImporter, + savedObjectTagAssignmentService, + savedObjectTagClient, esClient, logger, installedPkg, @@ -68,6 +72,8 @@ export async function _installPackage({ }: { savedObjectsClient: SavedObjectsClientContract; savedObjectsImporter: Pick; + savedObjectTagAssignmentService: IAssignmentService; + savedObjectTagClient: ITagsClient; esClient: ElasticsearchClient; logger: Logger; installedPkg?: SavedObject; @@ -78,7 +84,7 @@ export async function _installPackage({ spaceId: string; verificationResult?: PackageVerificationResult; }): Promise { - const { name: pkgName, version: pkgVersion } = packageInfo; + const { name: pkgName, version: pkgVersion, title: pkgTitle } = packageInfo; try { // if some installation already exists @@ -120,7 +126,10 @@ export async function _installPackage({ installKibanaAssetsAndReferences({ savedObjectsClient, savedObjectsImporter, + savedObjectTagAssignmentService, + savedObjectTagClient, pkgName, + pkgTitle, paths, installedPkg, logger, diff --git a/x-pack/plugins/fleet/server/services/epm/packages/install.test.ts b/x-pack/plugins/fleet/server/services/epm/packages/install.test.ts index ac53717bb2b1a..c58700716d18a 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/install.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/install.test.ts @@ -32,6 +32,10 @@ jest.mock('../../app_context', () => { getSavedObjects: jest.fn(() => ({ createImporter: jest.fn(), })), + getSavedObjectsTagging: jest.fn(() => ({ + createInternalAssignmentService: jest.fn(), + createTagClient: jest.fn(), + })), }, }; }); diff --git a/x-pack/plugins/fleet/server/services/epm/packages/install.ts b/x-pack/plugins/fleet/server/services/epm/packages/install.ts index 0794f43ea79e6..d66550570d1fe 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/install.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/install.ts @@ -362,11 +362,21 @@ async function installPackageFromRegistry({ .getSavedObjects() .createImporter(savedObjectsClient); + const savedObjectTagAssignmentService = appContextService + .getSavedObjectsTagging() + .createInternalAssignmentService({ client: savedObjectsClient }); + + const savedObjectTagClient = appContextService + .getSavedObjectsTagging() + .createTagClient({ client: savedObjectsClient }); + // try installing the package, if there was an error, call error handler and rethrow // @ts-expect-error status is string instead of InstallResult.status 'installed' | 'already_installed' return await _installPackage({ savedObjectsClient, savedObjectsImporter, + savedObjectTagAssignmentService, + savedObjectTagClient, esClient, logger, installedPkg, @@ -477,10 +487,20 @@ async function installPackageByUpload({ .getSavedObjects() .createImporter(savedObjectsClient); + const savedObjectTagAssignmentService = appContextService + .getSavedObjectsTagging() + .createInternalAssignmentService({ client: savedObjectsClient }); + + const savedObjectTagClient = appContextService + .getSavedObjectsTagging() + .createTagClient({ client: savedObjectsClient }); + // @ts-expect-error status is string instead of InstallResult.status 'installed' | 'already_installed' return await _installPackage({ savedObjectsClient, savedObjectsImporter, + savedObjectTagAssignmentService, + savedObjectTagClient, esClient, logger, installedPkg, diff --git a/x-pack/plugins/saved_objects_tagging/common/assignments.ts b/x-pack/plugins/saved_objects_tagging/common/assignments.ts index 7692a9151c47e..c69419b75871a 100644 --- a/x-pack/plugins/saved_objects_tagging/common/assignments.ts +++ b/x-pack/plugins/saved_objects_tagging/common/assignments.ts @@ -26,6 +26,7 @@ export interface UpdateTagAssignmentsOptions { tags: string[]; assign: ObjectReference[]; unassign: ObjectReference[]; + refresh?: boolean | 'wait_for'; } export interface FindAssignableObjectsOptions { diff --git a/x-pack/plugins/saved_objects_tagging/server/services/assignments/assignment_service.test.ts b/x-pack/plugins/saved_objects_tagging/server/services/assignments/assignment_service.test.ts index 61e4fbc2fb651..ec1a6575d2e3d 100644 --- a/x-pack/plugins/saved_objects_tagging/server/services/assignments/assignment_service.test.ts +++ b/x-pack/plugins/saved_objects_tagging/server/services/assignments/assignment_service.test.ts @@ -154,21 +154,56 @@ describe('AssignmentService', () => { }); expect(savedObjectClient.bulkUpdate).toHaveBeenCalledTimes(1); - expect(savedObjectClient.bulkUpdate).toHaveBeenCalledWith([ + expect(savedObjectClient.bulkUpdate).toHaveBeenCalledWith( + [ + { + type: 'dashboard', + id: 'dash-1', + attributes: {}, + references: [createReference('tag', 'tag-1'), createReference('tag', 'tag-2')], + }, + { + type: 'map', + id: 'map-1', + attributes: {}, + references: [createReference('dashboard', 'dash-1')], + }, + ], + { refresh: undefined } + ); + }); + }); + + it('calls `soClient.bulkUpdate` to update the references with refresh false', async () => { + savedObjectClient.bulkGet.mockResolvedValue({ + saved_objects: [ + createSavedObject({ + type: 'dashboard', + id: 'dash-1', + references: [], + }), + ], + }); + getUpdatableSavedObjectTypesMock.mockResolvedValue(['dashboard']); + + await service.updateTagAssignments({ + tags: ['tag-1', 'tag-2'], + assign: [{ type: 'dashboard', id: 'dash-1' }], + unassign: [], + refresh: false, + }); + + expect(savedObjectClient.bulkUpdate).toHaveBeenCalledWith( + [ { type: 'dashboard', id: 'dash-1', attributes: {}, references: [createReference('tag', 'tag-1'), createReference('tag', 'tag-2')], }, - { - type: 'map', - id: 'map-1', - attributes: {}, - references: [createReference('dashboard', 'dash-1')], - }, - ]); - }); + ], + { refresh: false } + ); }); describe('#findAssignableObjects', () => { diff --git a/x-pack/plugins/saved_objects_tagging/server/services/assignments/assignment_service.ts b/x-pack/plugins/saved_objects_tagging/server/services/assignments/assignment_service.ts index 09a726db856c2..9aeef11d606e8 100644 --- a/x-pack/plugins/saved_objects_tagging/server/services/assignments/assignment_service.ts +++ b/x-pack/plugins/saved_objects_tagging/server/services/assignments/assignment_service.ts @@ -106,7 +106,12 @@ export class AssignmentService { }); } - public async updateTagAssignments({ tags, assign, unassign }: UpdateTagAssignmentsOptions) { + public async updateTagAssignments({ + tags, + assign, + unassign, + refresh, + }: UpdateTagAssignmentsOptions) { const updatedTypes = uniq([...assign, ...unassign].map(({ type }) => type)); const untaggableTypes = difference(updatedTypes, taggableTypes); @@ -149,7 +154,7 @@ export class AssignmentService { }; }); - await this.soClient.bulkUpdate(updatedObjects); + await this.soClient.bulkUpdate(updatedObjects, { refresh }); } } diff --git a/x-pack/plugins/saved_objects_tagging/server/services/tags/tags_client.test.ts b/x-pack/plugins/saved_objects_tagging/server/services/tags/tags_client.test.ts index 6d3b6011cac99..7743b109dbd61 100644 --- a/x-pack/plugins/saved_objects_tagging/server/services/tags/tags_client.test.ts +++ b/x-pack/plugins/saved_objects_tagging/server/services/tags/tags_client.test.ts @@ -58,7 +58,20 @@ describe('TagsClient', () => { await tagsClient.create(attributes); expect(soClient.create).toHaveBeenCalledTimes(1); - expect(soClient.create).toHaveBeenCalledWith('tag', attributes); + expect(soClient.create).toHaveBeenCalledWith('tag', attributes, undefined); + }); + + it('calls `soClient.create` with options', async () => { + const attributes = createAttributes(); + + await tagsClient.create(attributes, { id: '1', overwrite: true, refresh: false }); + + expect(soClient.create).toHaveBeenCalledTimes(1); + expect(soClient.create).toHaveBeenCalledWith('tag', attributes, { + id: '1', + overwrite: true, + refresh: false, + }); }); it('converts the object returned from the soClient to a `Tag`', async () => { diff --git a/x-pack/plugins/saved_objects_tagging/server/services/tags/tags_client.ts b/x-pack/plugins/saved_objects_tagging/server/services/tags/tags_client.ts index 5535e334c06fb..23e1da56d6143 100644 --- a/x-pack/plugins/saved_objects_tagging/server/services/tags/tags_client.ts +++ b/x-pack/plugins/saved_objects_tagging/server/services/tags/tags_client.ts @@ -6,6 +6,7 @@ */ import { SavedObjectsClientContract } from '@kbn/core/server'; +import { CreateTagOptions } from '@kbn/saved-objects-tagging-oss-plugin/common/types'; import { TagSavedObject, TagAttributes, ITagsClient } from '../../../common/types'; import { tagSavedObjectTypeName } from '../../../common/constants'; import { TagValidationError } from './errors'; @@ -24,12 +25,12 @@ export class TagsClient implements ITagsClient { this.soClient = client; } - public async create(attributes: TagAttributes) { + public async create(attributes: TagAttributes, options?: CreateTagOptions) { const validation = validateTag(attributes); if (!validation.valid) { throw new TagValidationError('Error validating tag attributes', validation); } - const raw = await this.soClient.create(this.type, attributes); + const raw = await this.soClient.create(this.type, attributes, options); return savedObjectToTag(raw); } 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 de1b562b578b0..5753329ac34a5 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 @@ -140,6 +140,11 @@ export default function (providerContext: FtrProviderContext) { }, }) .expect(200); + const { body } = await supertest + .get(`/internal/saved_objects_tagging/tags/_find?page=1&perPage=10000`) + .expect(200); + expect(body.tags.find((tag: any) => tag.name === 'Managed').relationCount).to.be(6); + expect(body.tags.find((tag: any) => tag.name === 'For File Tests').relationCount).to.be(6); }); it('should return a 400 with an empty namespace', async function () { diff --git a/x-pack/test/saved_object_tagging/api_integration/security_and_spaces/config.ts b/x-pack/test/saved_object_tagging/api_integration/security_and_spaces/config.ts index 0e2ecc8c48ebf..e52664d02df64 100644 --- a/x-pack/test/saved_object_tagging/api_integration/security_and_spaces/config.ts +++ b/x-pack/test/saved_object_tagging/api_integration/security_and_spaces/config.ts @@ -31,6 +31,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { serverArgs: [ ...apiIntegrationConfig.get('kbnTestServer.serverArgs'), '--server.xsrf.disableProtection=true', + `--xpack.fleet.registryUrl=http://localhost:12345`, // setting to invalid registry url to prevent installing preconfigured packages ], }, }; diff --git a/x-pack/test/saved_object_tagging/functional/config.ts b/x-pack/test/saved_object_tagging/functional/config.ts index 1c40864f2fa02..cdf637cb40c66 100644 --- a/x-pack/test/saved_object_tagging/functional/config.ts +++ b/x-pack/test/saved_object_tagging/functional/config.ts @@ -33,7 +33,10 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { kbnTestServer: { ...kibanaFunctionalConfig.get('kbnTestServer'), - serverArgs: [...kibanaFunctionalConfig.get('kbnTestServer.serverArgs')], + serverArgs: [ + ...kibanaFunctionalConfig.get('kbnTestServer.serverArgs'), + `--xpack.fleet.registryUrl=http://localhost:12345`, // setting to invalid registry url to prevent installing preconfigured packages + ], }, }; }