Skip to content

move reindexing servce into its own class #221204

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 17 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,45 @@
import { offeringBasedSchema, schema, TypeOf } from '@kbn/config-schema';
import { PluginConfigDescriptor } from '@kbn/core/server';

export const dataSourceExclusionsSchema = schema.recordOf(
schema.string(),
schema.arrayOf(schema.oneOf([schema.literal('readOnly'), schema.literal('reindex')])),
{ defaultValue: {} }
);

export const featureSetSchema = schema.object({
/**
* Ml Snapshot should only be enabled for major version upgrades. Currently this
* is manually set to `true` on every `x.last` version.
* ML Upgrade mode can be toggled from outside Kibana, the purpose
* of this feature guard is to hide all ML related deprecations from the end user
* until the next major upgrade.
*
* When we want to enable ML model snapshot deprecation warnings again we need
* to change the constant `MachineLearningField.MIN_CHECKED_SUPPORTED_SNAPSHOT_VERSION`
* to something higher than 7.0.0 in the Elasticsearch code.
*/
mlSnapshots: schema.boolean({ defaultValue: true }),
/**
* Migrating system indices should only be enabled for major version upgrades.
* Currently this is manually set to `true` on every `x.last` version.
*/
migrateSystemIndices: schema.boolean({ defaultValue: true }),
/**
* Deprecations with reindexing corrective actions are only enabled for major version upgrades.
* Currently this is manually set to `true` on every `x.last` version.
*
* The reindex action includes some logic that is specific to the 8.0 upgrade
* End users could get into a bad situation if this is enabled before this logic is fixed.
*/
reindexCorrectiveActions: schema.boolean({ defaultValue: true }),
/**
* Migrating deprecated data streams should only be enabled for major version upgrades.
* Currently this is manually set to `true` on every `x.last` version.
*/
migrateDataStreams: schema.boolean({ defaultValue: true }),
});

// -------------------------------
// >= 8.6 UA is always enabled to guide stack upgrades
// even for minor releases.
Expand All @@ -31,44 +70,8 @@ const configSchema = schema.object({
* xpack.upgrade_assistant.dataSourceExclusions:
* 7_17_data_stream: ["readOnly"]
*/
dataSourceExclusions: schema.recordOf(
schema.string(),
schema.arrayOf(schema.oneOf([schema.literal('readOnly'), schema.literal('reindex')])),
{ defaultValue: {} }
),

featureSet: schema.object({
/**
* Ml Snapshot should only be enabled for major version upgrades. Currently this
* is manually set to `true` on every `x.last` version.
* ML Upgrade mode can be toggled from outside Kibana, the purpose
* of this feature guard is to hide all ML related deprecations from the end user
* until the next major upgrade.
*
* When we want to enable ML model snapshot deprecation warnings again we need
* to change the constant `MachineLearningField.MIN_CHECKED_SUPPORTED_SNAPSHOT_VERSION`
* to something higher than 7.0.0 in the Elasticsearch code.
*/
mlSnapshots: schema.boolean({ defaultValue: true }),
/**
* Migrating system indices should only be enabled for major version upgrades.
* Currently this is manually set to `true` on every `x.last` version.
*/
migrateSystemIndices: schema.boolean({ defaultValue: true }),
/**
* Deprecations with reindexing corrective actions are only enabled for major version upgrades.
* Currently this is manually set to `true` on every `x.last` version.
*
* The reindex action includes some logic that is specific to the 8.0 upgrade
* End users could get into a bad situation if this is enabled before this logic is fixed.
*/
reindexCorrectiveActions: schema.boolean({ defaultValue: true }),
/**
* Migrating deprecated data streams should only be enabled for major version upgrades.
* Currently this is manually set to `true` on every `x.last` version.
*/
migrateDataStreams: schema.boolean({ defaultValue: true }),
}),
dataSourceExclusions: dataSourceExclusionsSchema,
featureSet: featureSetSchema,
/**
* This config allows to hide the UI without disabling the plugin.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import {
CoreStart,
PluginInitializerContext,
Logger,
SavedObjectsClient,
SavedObjectsServiceStart,
} from '@kbn/core/server';
import { SecurityPluginStart } from '@kbn/security-plugin/server';
Expand All @@ -24,21 +23,16 @@ import { LicensingPluginSetup } from '@kbn/licensing-plugin/server';
import { DEPRECATION_LOGS_SOURCE_ID, DEPRECATION_LOGS_INDEX } from '../common/constants';

import { CredentialStore, credentialStoreFactory } from './lib/reindexing/credential_store';
import { ReindexWorker } from './lib/reindexing';
import { registerUpgradeAssistantUsageCollector } from './lib/telemetry';
import { versionService } from './lib/version';
import { createReindexWorker } from './routes/reindex_indices';
import { registerRoutes } from './routes/register_routes';
import {
reindexOperationSavedObjectType,
mlSavedObjectType,
hiddenTypes,
} from './saved_object_types';
import { reindexOperationSavedObjectType, mlSavedObjectType } from './saved_object_types';
import { handleEsError } from './shared_imports';
import { RouteDependencies } from './types';
import type { UpgradeAssistantConfig } from './config';
import type { DataSourceExclusions, FeatureSet } from '../common/types';
import { defaultExclusions } from './lib/data_source_exclusions';
import { ReindexingService } from './reindexing_service';

interface PluginsSetup {
usageCollection: UsageCollectionSetup;
Expand All @@ -59,40 +53,33 @@ export class UpgradeAssistantServerPlugin implements Plugin {
private readonly initialFeatureSet: FeatureSet;
private readonly initialDataSourceExclusions: DataSourceExclusions;

// Properties set at setup
private licensing?: LicensingPluginSetup;

// Properties set at start
private savedObjectsServiceStart?: SavedObjectsServiceStart;
private securityPluginStart?: SecurityPluginStart;
private worker?: ReindexWorker;

private reindexingService?: ReindexingService;

constructor({ logger, env, config }: PluginInitializerContext<UpgradeAssistantConfig>) {
this.logger = logger.get();
// used by worker and passed to routes
this.credentialStore = credentialStoreFactory(this.logger);
this.kibanaVersion = env.packageInfo.version;

const { featureSet, dataSourceExclusions } = config.get();
this.initialFeatureSet = featureSet;
this.initialDataSourceExclusions = Object.assign({}, defaultExclusions, dataSourceExclusions);
this.reindexingService = new ReindexingService({ logger: this.logger, config });
}

private getWorker() {
if (!this.worker) {
throw new Error('Worker unavailable');
}
return this.worker;
}

setup(
{ http, deprecations, getStartServices, savedObjects, docLinks }: CoreSetup,
{ usageCollection, features, licensing, logsShared, security }: PluginsSetup
) {
this.licensing = licensing;
setup(coreSetup: CoreSetup, pluginSetup: PluginsSetup) {
const { http, getStartServices, savedObjects } = coreSetup;
const { usageCollection, features, licensing, logsShared, security } = pluginSetup;

savedObjects.registerType(reindexOperationSavedObjectType);
savedObjects.registerType(mlSavedObjectType);

this.reindexingService?.setup(coreSetup, pluginSetup);

features.registerElasticsearchFeature({
id: 'upgrade_assistant',
management: {
Expand Down Expand Up @@ -149,7 +136,7 @@ export class UpgradeAssistantServerPlugin implements Plugin {
defaultTarget: versionService.getNextMajorVersion(),
};

registerRoutes(dependencies, this.getWorker.bind(this));
registerRoutes(dependencies);

if (usageCollection) {
void getStartServices().then(([{ elasticsearch }]) => {
Expand All @@ -172,23 +159,11 @@ export class UpgradeAssistantServerPlugin implements Plugin {
// process jobs without the browser staying on the page, but will require that jobs go into
// a paused state if no Kibana nodes have the required credentials.

this.worker = createReindexWorker({
credentialStore: this.credentialStore,
licensing: this.licensing!,
elasticsearchService: elasticsearch,
logger: this.logger,
savedObjects: new SavedObjectsClient(
this.savedObjectsServiceStart.createInternalRepository(hiddenTypes)
),
security: this.securityPluginStart,
});

this.worker.start();
// The ReindexWorker will use the credentials stored in the cache to reindex the data
this.reindexingService?.start({ savedObjects, elasticsearch }, { security });
}

stop(): void {
if (this.worker) {
this.worker.stop();
}
this.reindexingService?.stop();
}
}
Original file line number Diff line number Diff line change
@@ -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.
*/

export const createRequestMock = (opts?: {
headers?: any;
params?: Record<string, any>;
query?: Record<string, any>;
body?: Record<string, any>;
}) => {
return Object.assign({ headers: {} }, opts || {});
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* 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 { AwaitedProperties } from '@kbn/utility-types';
import { RequestHandler, RequestHandlerContext } from '@kbn/core/server';
import {
elasticsearchServiceMock,
savedObjectsClientMock,
deprecationsServiceMock,
} from '@kbn/core/server/mocks';

export const savedObjectsClient = savedObjectsClientMock.create();
export const routeHandlerContextMock = {
core: {
elasticsearch: {
client: elasticsearchServiceMock.createScopedClusterClient(),
},
savedObjects: { getClient: () => savedObjectsClient },
deprecations: { client: deprecationsServiceMock.createClient() },
},
} as unknown as AwaitedProperties<RequestHandlerContext>;

/**
* Creates a very crude mock of the new platform router implementation. This enables use to test
* controller/handler logic without making HTTP requests to an actual server. This does not enable
* us to test whether our paths actual match, only the response codes of controllers given certain
* inputs. This should be replaced by a more wholistic solution (like functional tests) eventually.
*
* This also bypasses any validation installed on the route.
*/
export const createMockRouter = () => {
const paths: Record<string, Record<string, RequestHandler<any, any, any>>> = {};

const assign =
(method: string) =>
({ path }: { path: string }, handler: RequestHandler<any, any, any>) => {
paths[method] = {
...(paths[method] || {}),
...{ [path]: handler },
};
};

return {
getHandler({ method, pathPattern }: { method: string; pathPattern: string }) {
return paths[method][pathPattern];
},
get: assign('get'),
post: assign('post'),
put: assign('put'),
patch: assign('patch'),
delete: assign('delete'),
};
};

export type MockRouter = ReturnType<typeof createMockRouter>;
Original file line number Diff line number Diff line change
@@ -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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { schema, TypeOf } from '@kbn/config-schema';
import { dataSourceExclusionsSchema, featureSetSchema } from '../config';

const configSchema = schema.object({
dataSourceExclusions: dataSourceExclusionsSchema,
featureSet: featureSetSchema,
});

export type ReindexingServiceConfig = TypeOf<typeof configSchema>;
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import { ElasticsearchServiceStart, Logger, SavedObjectsClient } from '@kbn/core

import { LicensingPluginSetup } from '@kbn/licensing-plugin/server';
import { SecurityPluginStart } from '@kbn/security-plugin/server';
import { ReindexWorker } from '../../lib/reindexing';
import { CredentialStore } from '../../lib/reindexing/credential_store';
import { ReindexWorker } from '../lib/reindexing';
import { CredentialStore } from '../lib/reindexing/credential_store';

interface CreateReindexWorker {
logger: Logger;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

export { ReindexingService } from './reindexing_service';
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

export { reindexHandler } from './reindex_handler';
Loading