Skip to content

Commit

Permalink
Merge branch 'main' into remove-deprecated-rule-apis
Browse files Browse the repository at this point in the history
  • Loading branch information
js-jankisalvi authored Dec 16, 2024
2 parents edd060c + eb1c70a commit bbfb545
Show file tree
Hide file tree
Showing 142 changed files with 1,782 additions and 1,340 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import type {
DeprecationsRequestHandlerContext,
DeprecationsClient,
} from '@kbn/core-deprecations-server';
import type { KibanaRequest } from '@kbn/core-http-server';
import type { InternalDeprecationsServiceStart } from './deprecations_service';

/**
Expand All @@ -25,14 +26,16 @@ export class CoreDeprecationsRouteHandlerContext implements DeprecationsRequestH
constructor(
private readonly deprecationsStart: InternalDeprecationsServiceStart,
private readonly elasticsearchRouterHandlerContext: CoreElasticsearchRouteHandlerContext,
private readonly savedObjectsRouterHandlerContext: CoreSavedObjectsRouteHandlerContext
private readonly savedObjectsRouterHandlerContext: CoreSavedObjectsRouteHandlerContext,
private readonly request: KibanaRequest
) {}

public get client() {
if (this.#client == null) {
this.#client = this.deprecationsStart.asScopedToClient(
this.elasticsearchRouterHandlerContext.client,
this.savedObjectsRouterHandlerContext.client
this.savedObjectsRouterHandlerContext.client,
this.request
);
}
return this.#client;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
registerConfigDeprecationsInfoMock,
} from './deprecations_service.test.mocks';
import { mockCoreContext } from '@kbn/core-base-server-mocks';
import { httpServiceMock } from '@kbn/core-http-server-mocks';
import { httpServerMock, httpServiceMock } from '@kbn/core-http-server-mocks';
import { coreUsageDataServiceMock } from '@kbn/core-usage-data-server-mocks';
import { configServiceMock } from '@kbn/config-mocks';
import { savedObjectsClientMock } from '@kbn/core-saved-objects-api-server-mocks';
Expand Down Expand Up @@ -83,12 +83,13 @@ describe('DeprecationsService', () => {
it('returns client with #getAllDeprecations method', async () => {
const esClient = elasticsearchServiceMock.createScopedClusterClient();
const savedObjectsClient = savedObjectsClientMock.create();
const request = httpServerMock.createKibanaRequest();
const deprecationsService = new DeprecationsService(coreContext);

await deprecationsService.setup(deprecationsCoreSetupDeps);

const start = deprecationsService.start();
const deprecationsClient = start.asScopedToClient(esClient, savedObjectsClient);
const deprecationsClient = start.asScopedToClient(esClient, savedObjectsClient, request);

expect(deprecationsClient.getAllDeprecations).toBeDefined();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,25 @@ import type {
DeprecationsClient,
} from '@kbn/core-deprecations-server';
import { InternalCoreUsageDataSetup } from '@kbn/core-usage-data-base-server-internal';
import type { KibanaRequest } from '@kbn/core-http-server';
import { DeprecationsFactory } from './deprecations_factory';
import { registerRoutes } from './routes';
import { config as deprecationConfig, DeprecationConfigType } from './deprecation_config';
import { registerApiDeprecationsInfo, registerConfigDeprecationsInfo } from './deprecations';

/**
* Deprecation Service: Internal Start contract
*/
export interface InternalDeprecationsServiceStart {
/**
* Creates a {@link DeprecationsClient} with provided SO client and ES client.
*
* @param esClient Scoped Elasticsearch client
* @param savedObjectsClient Scoped SO Client
*/
asScopedToClient(
esClient: IScopedClusterClient,
savedObjectsClient: SavedObjectsClientContract
savedObjectsClient: SavedObjectsClientContract,
request: KibanaRequest
): DeprecationsClient;
}

Expand Down Expand Up @@ -113,13 +119,19 @@ export class DeprecationsService

private createScopedDeprecations(): (
esClient: IScopedClusterClient,
savedObjectsClient: SavedObjectsClientContract
savedObjectsClient: SavedObjectsClientContract,
request: KibanaRequest
) => DeprecationsClient {
return (esClient: IScopedClusterClient, savedObjectsClient: SavedObjectsClientContract) => {
return (
esClient: IScopedClusterClient,
savedObjectsClient: SavedObjectsClientContract,
request: KibanaRequest
) => {
return {
getAllDeprecations: this.deprecationsFactory!.getAllDeprecations.bind(null, {
savedObjectsClient,
esClient,
request,
}),
};
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { elasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-m
import type { GetDeprecationsContext } from '@kbn/core-deprecations-server';
import { savedObjectsClientMock } from '@kbn/core-saved-objects-api-server-mocks';
import type { DeprecationsRegistry } from '../deprecations_registry';
import { httpServerMock } from '@kbn/core-http-server-mocks';

type DeprecationsRegistryContract = PublicMethodsOf<DeprecationsRegistry>;

Expand All @@ -28,6 +29,7 @@ const createGetDeprecationsContextMock = () => {
const mocked: jest.Mocked<GetDeprecationsContext> = {
esClient: elasticsearchClientMock.createScopedClusterClient(),
savedObjectsClient: savedObjectsClientMock.create(),
request: httpServerMock.createKibanaRequest(),
};

return mocked;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import type { MaybePromise } from '@kbn/utility-types';
import type { DeprecationsDetails } from '@kbn/core-deprecations-common';
import type { IScopedClusterClient } from '@kbn/core-elasticsearch-server';
import type { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server';
import type { KibanaRequest } from '@kbn/core-http-server';

/**
* The deprecations service provides a way for the Kibana platform to communicate deprecated
Expand Down Expand Up @@ -87,27 +88,51 @@ import type { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-ser
* @public
*/
export interface DeprecationsServiceSetup {
/**
* Registers deprecation messages or notices for a specific feature or functionality
* within the application. This allows developers to flag certain behaviors or APIs
* as deprecated, providing guidance and warnings for future deprecation plans.
*
* @param {RegisterDeprecationsConfig} deprecationContext - The configuration object containing
* information about the deprecated features, including messages, corrective actions,
* and any relevant metadata to inform users or developers about the deprecation.
*/
registerDeprecations: (deprecationContext: RegisterDeprecationsConfig) => void;
}

/**
* Options to provide when registering deprecations via {@link DeprecationsServiceSetup.registerDeprecations}.
* @public
*/
export interface RegisterDeprecationsConfig {
/**
* Method called when the user wants to list any existing deprecations.
* Returns the list of deprecation messages to warn about.
* @param {GetDeprecationsContext} context Scoped clients and helpers to ease fetching the deprecations.
*/
getDeprecations: (context: GetDeprecationsContext) => MaybePromise<DeprecationsDetails[]>;
}

/**
* Scoped clients and helpers to ease fetching the deprecations.
* @public
*/
export interface GetDeprecationsContext {
/** Elasticsearch client scoped to the current user */
esClient: IScopedClusterClient;
/** Saved Objects client scoped to the current user and space */
savedObjectsClient: SavedObjectsClientContract;
request: KibanaRequest;
}

/**
* Provides a method to scope the {@link DeprecationsServiceSetup | Deprecations Service} to a specific domain.
* @public
*/
export interface DeprecationRegistryProvider {
/**
* Returns the {@link DeprecationsServiceSetup | Deprecations Service} scoped to a specific domain.
* @param domainId Domain ID to categorize the deprecations reported under it.
*/
getRegistry: (domainId: string) => DeprecationsServiceSetup;
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ import type { DomainDeprecationDetails } from '@kbn/core-deprecations-common';
* @public
*/
export interface DeprecationsClient {
/**
* Fetch all Kibana deprecations.
*/
getAllDeprecations: () => Promise<DomainDeprecationDetails[]>;
}

Expand All @@ -23,5 +26,8 @@ export interface DeprecationsClient {
* @public
*/
export interface DeprecationsRequestHandlerContext {
/**
* {@link DeprecationsClient | Deprecations client} exposed in the request handler context.
*/
client: DeprecationsClient;
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"@kbn/core-deprecations-common",
"@kbn/core-elasticsearch-server",
"@kbn/core-saved-objects-api-server",
"@kbn/core-http-server",
],
"exclude": [
"target/**/*",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,8 @@ export class CoreRouteHandlerContext implements CoreRequestHandlerContext {
this.#deprecations = new CoreDeprecationsRouteHandlerContext(
this.coreStart.deprecations,
this.elasticsearch,
this.savedObjects
this.savedObjects,
this.request
);
}
return this.#deprecations;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,23 @@ import {

import { SavedObjectsRepository } from './repository';
import { loggerMock } from '@kbn/logging-mocks';
import { SavedObjectsSerializer } from '@kbn/core-saved-objects-base-server-internal';
import { kibanaMigratorMock } from '../mocks';
import { elasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-mocks';

import {
mockTimestamp,
mappings,
createRegistry,
createDocumentMigrator,
createSpySerializer,
} from '../test_helpers/repository.test.common';
import type { ISavedObjectsRepository } from '@kbn/core-saved-objects-api-server';
import { ISavedObjectsSpacesExtension } from '@kbn/core-saved-objects-server';
import { savedObjectsExtensionsMock } from '../mocks/saved_objects_extensions.mock';

describe('SavedObjectsRepository', () => {
let client: ReturnType<typeof elasticsearchClientMock.createElasticsearchClient>;
let repository: SavedObjectsRepository;
let repository: ISavedObjectsRepository;
let migrator: ReturnType<typeof kibanaMigratorMock.create>;
let logger: ReturnType<typeof loggerMock.create>;
let serializer: jest.Mocked<SavedObjectsSerializer>;

const registry = createRegistry();
const documentMigrator = createDocumentMigrator(registry);
Expand All @@ -46,23 +45,13 @@ describe('SavedObjectsRepository', () => {
migrator.runMigrations = jest.fn().mockResolvedValue([{ status: 'skipped' }]);
logger = loggerMock.create();

// create a mock serializer "shim" so we can track function calls, but use the real serializer's implementation
serializer = createSpySerializer(registry);

const allTypes = registry.getAllTypes().map((type) => type.name);
const allowedTypes = [...new Set(allTypes.filter((type) => !registry.isHidden(type)))];

// @ts-expect-error must use the private constructor to use the mocked serializer
repository = new SavedObjectsRepository({
index: '.kibana-test',
mappings,
client,
repository = SavedObjectsRepository.createRepository(
migrator,
typeRegistry: registry,
serializer,
allowedTypes,
logger,
});
registry,
'.kibana-test',
client,
logger
);

mockGetCurrentTime.mockReturnValue(mockTimestamp);
mockGetSearchDsl.mockClear();
Expand All @@ -87,4 +76,60 @@ describe('SavedObjectsRepository', () => {
expect(repository.getCurrentNamespace('space-a')).toBe('space-a');
});
});

describe('#asScopedToNamespace', () => {
it('returns a new client with undefined spacesExtensions (not available)', () => {
const scopedRepository = repository.asScopedToNamespace('space-a');
expect(scopedRepository).toBeInstanceOf(SavedObjectsRepository);
expect(scopedRepository).not.toStrictEqual(repository);

// Checking extensions.spacesExtension are both undefined
// @ts-expect-error type is ISavedObjectsRepository, but in reality is SavedObjectsRepository
expect(repository.extensions.spacesExtension).toBeUndefined();
// @ts-expect-error type is ISavedObjectsRepository, but in reality is SavedObjectsRepository
expect(scopedRepository.extensions.spacesExtension).toBeUndefined();
// @ts-expect-error type is ISavedObjectsRepository, but in reality is SavedObjectsRepository
expect(scopedRepository.extensions.spacesExtension).toStrictEqual(
// @ts-expect-error type is ISavedObjectsRepository, but in reality is SavedObjectsRepository
repository.extensions.spacesExtension
);
});
});

describe('with spacesExtension', () => {
let spacesExtension: jest.Mocked<ISavedObjectsSpacesExtension>;

beforeEach(() => {
spacesExtension = savedObjectsExtensionsMock.createSpacesExtension();
repository = SavedObjectsRepository.createRepository(
migrator,
registry,
'.kibana-test',
client,
logger,
[],
{ spacesExtension }
);
});

describe('#asScopedToNamespace', () => {
it('returns a new client with space-scoped spacesExtensions', () => {
const scopedRepository = repository.asScopedToNamespace('space-a');
expect(scopedRepository).toBeInstanceOf(SavedObjectsRepository);
expect(scopedRepository).not.toStrictEqual(repository);
expect(spacesExtension.asScopedToNamespace).toHaveBeenCalledWith('space-a');

// Checking extensions.spacesExtension are both defined but different
// @ts-expect-error type is ISavedObjectsRepository, but in reality is SavedObjectsRepository
expect(repository.extensions.spacesExtension).not.toBeUndefined();
// @ts-expect-error type is ISavedObjectsRepository, but in reality is SavedObjectsRepository
expect(scopedRepository.extensions.spacesExtension).not.toBeUndefined();
// @ts-expect-error type is ISavedObjectsRepository, but in reality is SavedObjectsRepository
expect(scopedRepository.extensions.spacesExtension).not.toStrictEqual(
// @ts-expect-error type is ISavedObjectsRepository, but in reality is SavedObjectsRepository
repository.extensions.spacesExtension
);
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ export class SavedObjectsRepository implements ISavedObjectsRepository {
});
}

private constructor(options: SavedObjectsRepositoryOptions) {
private constructor(private readonly options: SavedObjectsRepositoryOptions) {
const {
index,
mappings,
Expand Down Expand Up @@ -564,4 +564,17 @@ export class SavedObjectsRepository implements ISavedObjectsRepository {
getCurrentNamespace(namespace?: string) {
return this.helpers.common.getCurrentNamespace(namespace);
}

/**
* {@inheritDoc ISavedObjectsRepository.asScopedToNamespace}
*/
asScopedToNamespace(namespace: string) {
return new SavedObjectsRepository({
...this.options,
extensions: {
...this.options.extensions,
spacesExtension: this.extensions.spacesExtension?.asScopedToNamespace(namespace),
},
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const createRepositoryMock = () => {
collectMultiNamespaceReferences: jest.fn(),
updateObjectsSpaces: jest.fn(),
getCurrentNamespace: jest.fn(),
asScopedToNamespace: jest.fn().mockImplementation(createRepositoryMock),
};

return mock;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ const createSecurityExtension = (): jest.Mocked<ISavedObjectsSecurityExtension>
const createSpacesExtension = (): jest.Mocked<ISavedObjectsSpacesExtension> => ({
getCurrentNamespace: jest.fn(),
getSearchableNamespaces: jest.fn(),
asScopedToNamespace: jest.fn().mockImplementation(createSpacesExtension),
});

const create = () => ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -335,4 +335,12 @@ describe('SavedObjectsClient', () => {
expect(client.getCurrentNamespace()).toEqual('ns');
expect(mockRepository.getCurrentNamespace).toHaveBeenCalledWith();
});

test('#asScopedToNamespace', () => {
const client = new SavedObjectsClient(mockRepository);

const rescopedClient = client.asScopedToNamespace('ns');
expect(rescopedClient).not.toStrictEqual(client);
expect(mockRepository.asScopedToNamespace).toHaveBeenCalledWith('ns');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -216,4 +216,9 @@ export class SavedObjectsClient implements SavedObjectsClientContract {
getCurrentNamespace() {
return this._repository.getCurrentNamespace();
}

/** {@inheritDoc SavedObjectsClientContract.asScopedToNamespace} */
asScopedToNamespace(namespace: string) {
return new SavedObjectsClient(this._repository.asScopedToNamespace(namespace));
}
}
Loading

0 comments on commit bbfb545

Please sign in to comment.