Skip to content
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

[ML] job saved objects initialization #82450

Closed
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
d37c5ae
[ML] job saved objects initialization
jgowdyelastic Nov 3, 2020
22b0497
fixing job count logic
jgowdyelastic Nov 3, 2020
fa95dcf
adding missing files
jgowdyelastic Nov 3, 2020
7934aa8
Merge branch 'master' into job-saved-object-initialization
kibanamachine Nov 3, 2020
77f56a2
[Workplace Search] Migrate shared LicenseBadge component (#82372)
scottybollinger Nov 3, 2020
8f3a094
attempting to fix build crash
jgowdyelastic Nov 3, 2020
dc3c384
Merge branch 'job-saved-object-initialization' of github.com:jgowdyel…
jgowdyelastic Nov 3, 2020
9259b1f
[Enterprise Search] Added App Search log settings routes (#82162)
JasonStoltz Nov 3, 2020
b3079b9
fixing kibana.json
jgowdyelastic Nov 3, 2020
ac33148
[DOCS] Updates index patterns docs (#81864)
gchaps Nov 3, 2020
adf0e24
[Enterprise Search] Telemetry: refactor to Kea logic file (#81926)
constancecchen Nov 3, 2020
b770e82
[Remote clusters] Reorganize test files (#82362)
cjcenizal Nov 3, 2020
ca53f77
skip flaky suite (#82445)
tylersmalley Nov 3, 2020
eb43158
Add descriptions to alert types (#81850)
mikecote Nov 3, 2020
f2aad12
[Resolver] Screenshot the nodes of the test plugin. (#81405)
Nov 3, 2020
1117800
[Security Solution] Fix host details query when missing IP (#78912)
patrykkopycinski Nov 3, 2020
e54d2c0
[Ingest Manager] Replace logs/metrics strings with const (#82424)
Nov 3, 2020
6689167
[Lens] Drag within dimension group to reorder (#80547)
mbondyra Nov 3, 2020
39ce0cd
[Enterprise Search] Migrate shared CredentialItem component (#82471)
scottybollinger Nov 3, 2020
eeb314e
Prevent incompatable upgrade of crypto-policies (#82475)
Nov 3, 2020
9f776a2
skip flaky suite (#75127)
tylersmalley Nov 3, 2020
25f680e
Add more prompts to 8.0 breaking change issue template. (#82184)
cjcenizal Nov 3, 2020
0fec6cb
[ci] run server integration tests (#81698)
Nov 3, 2020
13dae5e
Switch to new 'as const' + typeof + ValueOf approach (#82499)
Nov 3, 2020
0bf7e32
Fixes ui strings around threat matching/mapping (#82510)
FrankHassanabad Nov 3, 2020
4323357
[Detection Rules] Add 7.10 rules - v3 (#82214)
brokensound77 Nov 3, 2020
74463a4
[Security Solution][Detections] Fixes bulk alert status update to onl…
spong Nov 3, 2020
b8307b4
[ML] Add probability values in decision path visualization for classi…
qn895 Nov 4, 2020
286dbca
[test] Updates rollup test to allow incoming doc_count field mapper (…
Nov 4, 2020
fb1c7d7
Fix saved object share UI bugs regarding read-only privileges (#81828)
jportner Nov 4, 2020
08d4ba6
clarify what "deps" term (#82465)
mshustov Nov 4, 2020
2c61de1
[Search][Dashboard] Restore searchSessionId from URL (#81489)
Dosant Nov 4, 2020
57f7401
[Lens] Add functional test for wrapping labels (#82453)
flash1293 Nov 4, 2020
7abb1e3
[Security Solution][Case] Case action type (#80870)
cnasikas Nov 4, 2020
fe3b053
[Lens] Categorical color palettes (#75309)
flash1293 Nov 4, 2020
ae3f4f5
[test/new_visualize_flow] fix config (#82441)
dmlemeshko Nov 4, 2020
64f50f8
Add moving average function (#82122)
mbondyra Nov 4, 2020
5a9fc25
[Enterprise Search] Migrate shared ApiKey component (#82511)
scottybollinger Nov 4, 2020
ae992ba
[Enterprise Search] Migrate shared ComponentLoader component (#82504)
scottybollinger Nov 4, 2020
c3f4024
[Ingest Manager] Switch DefaultPackage enum to approach from #82188 (…
Nov 4, 2020
e2cbde3
SavedObjects management: display explicit import error in case of fai…
pgayvallet Nov 4, 2020
e683ece
Index patterns api - load field list on server (#81218)
mattkime Nov 4, 2020
9bb8a41
[CI] Move notifyOnError to fix in-progress alerts for ciGroups (#82506)
brianseeders Nov 4, 2020
61a5407
remove entire suite as partial skips aren't doing the trick
spalger Oct 7, 2020
1d13937
Change monaco background color to match inputs (#82451)
ryankeairns Nov 4, 2020
c59ad36
[Enterprise Search] Trivial API fixes (#82552)
constancecchen Nov 4, 2020
c1b7830
TS project references for securityOss plugin (#82135)
smith Nov 4, 2020
b732d77
Merge branches 'job-saved-object-initialization' and 'job-saved-objec…
jgowdyelastic Nov 4, 2020
2dae54e
changes based on review
jgowdyelastic Nov 4, 2020
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
1 change: 1 addition & 0 deletions x-pack/plugins/ml/common/types/saved_objects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
*/

export type JobType = 'anomaly-detector' | 'data-frame-analytics';
export const ML_SAVED_OBJECT_TYPE = 'ml-job';
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import { HttpService } from '../http_service';

import { basePath } from './index';
import { JobType } from '../../../../common/types/saved_objects';

export const savedObjectsApiProvider = (httpService: HttpService) => ({
jobsSpaces() {
Expand All @@ -17,4 +18,20 @@ export const savedObjectsApiProvider = (httpService: HttpService) => ({
method: 'GET',
});
},
assignJobToSpace(jobType: JobType, jobIds: string[], spaces: string[]) {
const body = JSON.stringify({ jobType, jobIds, spaces });
return httpService.http<any>({
path: `${basePath()}/saved_objects/assign_job_to_space`,
method: 'POST',
body,
});
},
removeJobFromSpace(jobType: JobType, jobIds: string[], spaces: string[]) {
const body = JSON.stringify({ jobType, jobIds, spaces });
return httpService.http<any>({
path: `${basePath()}/saved_objects/remove_job_from_space`,
method: 'POST',
body,
});
},
});
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import { KibanaRequest } from 'kibana/server';
import type { MlClient } from '../../lib/ml_client';
import { mlLog } from '../../client/log';
import { mlLog } from '../../lib/log';
import {
MlCapabilities,
adminMlCapabilities,
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/ml/server/lib/capabilities/upgrade.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/

import type { MlClient } from '../../lib/ml_client';
import { mlLog } from '../../client/log';
import { mlLog } from '../../lib/log';

export function upgradeCheckProvider(mlClient: MlClient) {
async function isUpgradeInProgress(): Promise<boolean> {
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/ml/server/lib/check_annotations/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/

import { IScopedClusterClient } from 'kibana/server';
import { mlLog } from '../../client/log';
import { mlLog } from '../../lib/log';

import {
ML_ANNOTATIONS_INDEX_ALIAS_READ,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import { cloneDeep, each, remove, sortBy, get } from 'lodash';

import { mlLog } from '../../client/log';
import { mlLog } from '../../lib/log';

import { INTERVALS } from './intervals';
import { singleSeriesCheckerFactory } from './single_series_checker';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
* Bucket spans: 5m, 10m, 30m, 1h, 3h
*/

import { mlLog } from '../../client/log';
import { mlLog } from '../../lib/log';
import { INTERVALS, LONG_INTERVALS } from './intervals';

export function singleSeriesCheckerFactory({ asCurrentUser }) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import {
prefixDatafeedId,
splitIndexPatternNames,
} from '../../../common/util/job_utils';
import { mlLog } from '../../client/log';
import { mlLog } from '../../lib/log';
import { calculateModelMemoryLimitProvider } from '../calculate_model_memory_limit';
import { fieldsServiceProvider } from '../fields_service';
import { jobServiceProvider } from '../job_service';
Expand Down
11 changes: 8 additions & 3 deletions x-pack/plugins/ml/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { PLUGIN_ID } from '../common/constants/app';
import { MlCapabilities } from '../common/types/capabilities';

import { initMlTelemetry } from './lib/telemetry';
import { initMlServerLog } from './client/log';
import { initMlServerLog } from './lib/log';
import { initSampleDataSets } from './lib/sample_data_sets';

import { annotationRoutes } from './routes/annotations';
Expand All @@ -50,7 +50,7 @@ import { getPluginPrivileges } from '../common/types/capabilities';
import { setupCapabilitiesSwitcher } from './lib/capabilities';
import { registerKibanaSettings } from './lib/register_settings';
import { trainedModelsRoutes } from './routes/trained_models';
import { setupSavedObjects } from './saved_objects';
import { setupSavedObjects, jobInitializationFactory } from './saved_objects';
import { RouteGuard } from './lib/route_guard';

export type MlPluginSetup = SharedServices;
Expand Down Expand Up @@ -181,10 +181,15 @@ export class MlServerPlugin implements Plugin<MlPluginSetup, MlPluginStart, Plug
};
}

public start(coreStart: CoreStart): MlPluginStart {
public async start(coreStart: CoreStart): Promise<MlPluginStart> {
this.capabilities = coreStart.capabilities;
this.clusterClient = coreStart.elasticsearch.client;
this.savedObjectsStart = coreStart.savedObjects;

// check whether the job saved objects exist
// and create them if needed.
const { initializeJobs } = jobInitializationFactory(coreStart);
await initializeJobs();
}

public stop() {
Expand Down
6 changes: 3 additions & 3 deletions x-pack/plugins/ml/server/routes/saved_objects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import { wrapError } from '../client/error_wrapper';
import { RouteInitialization } from '../types';
import { checksFactory } from '../saved_objects';
import { checksFactory, repairFactory } from '../saved_objects';
import { jobsAndSpaces, repairJobObjects } from './schemas/saved_objects';

/**
Expand Down Expand Up @@ -67,7 +67,7 @@ export function savedObjectsRoutes({ router, routeGuard }: RouteInitialization)
routeGuard.fullLicenseAPIGuard(async ({ client, request, response, jobSavedObjectService }) => {
try {
const { simulate } = request.query;
const { repairJobs } = checksFactory(client, jobSavedObjectService);
const { repairJobs } = repairFactory(client, jobSavedObjectService);
const savedObjects = await repairJobs(simulate);

return response.ok({
Expand Down Expand Up @@ -100,7 +100,7 @@ export function savedObjectsRoutes({ router, routeGuard }: RouteInitialization)
routeGuard.fullLicenseAPIGuard(async ({ client, request, response, jobSavedObjectService }) => {
try {
const { simulate } = request.query;
const { initSavedObjects } = checksFactory(client, jobSavedObjectService);
const { initSavedObjects } = repairFactory(client, jobSavedObjectService);
const savedObjects = await initSavedObjects(simulate);

return response.ok({
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/ml/server/routes/system.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { schema } from '@kbn/config-schema';
import { Request } from '@hapi/hapi';
import { IScopedClusterClient } from 'kibana/server';
import { wrapError } from '../client/error_wrapper';
import { mlLog } from '../client/log';
import { mlLog } from '../lib/log';
import { capabilitiesProvider } from '../lib/capabilities';
import { spacesUtilsProvider } from '../lib/spaces_utils';
import { RouteInitialization, SystemRouteDeps } from '../types';
Expand Down
203 changes: 3 additions & 200 deletions x-pack/plugins/ml/server/saved_objects/checks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@
* you may not use this file except in compliance with the Elastic License.
*/

import Boom from '@hapi/boom';
import { IScopedClusterClient } from 'kibana/server';
import { SearchResponse } from 'elasticsearch';
import type { JobObject, JobSavedObjectService } from './service';
import { ML_SAVED_OBJECT_TYPE } from './saved_objects';
import { JobType } from '../../common/types/saved_objects';
import type { JobSavedObjectService } from './service';
import { JobType, ML_SAVED_OBJECT_TYPE } from '../../common/types/saved_objects';

import { Job } from '../../common/types/anomaly_detection_jobs';
import { Datafeed } from '../../common/types/anomaly_detection_jobs';
Expand Down Expand Up @@ -163,201 +161,6 @@ export function checksFactory(
};
}

async function repairJobs(simulate: boolean = false) {
type Result = Record<string, { success: boolean; error?: any }>;
const results: {
savedObjectsCreated: Result;
savedObjectsDeleted: Result;
datafeedsAdded: Result;
datafeedsRemoved: Result;
} = {
savedObjectsCreated: {},
savedObjectsDeleted: {},
datafeedsAdded: {},
datafeedsRemoved: {},
};

const { body: datafeeds } = await client.asInternalUser.ml.getDatafeeds<{
datafeeds: Datafeed[];
}>();

const tasks: Array<() => Promise<void>> = [];

const status = await checkStatus();
for (const job of status.jobs['anomaly-detector']) {
if (job.checks.savedObjectExits === false) {
if (simulate === true) {
results.savedObjectsCreated[job.jobId] = { success: true };
} else {
// create AD saved objects for jobs which are missing them
const jobId = job.jobId;
const datafeedId = job.datafeedId;
tasks.push(async () => {
try {
await jobSavedObjectService.createAnomalyDetectionJob(jobId, datafeedId ?? undefined);
results.savedObjectsCreated[job.jobId] = { success: true };
} catch (error) {
results.savedObjectsCreated[job.jobId] = {
success: false,
error: error.body ?? error,
};
}
});
}
}
}
for (const job of status.jobs['data-frame-analytics']) {
if (job.checks.savedObjectExits === false) {
if (simulate === true) {
results.savedObjectsCreated[job.jobId] = { success: true };
} else {
// create DFA saved objects for jobs which are missing them
const jobId = job.jobId;
tasks.push(async () => {
try {
await jobSavedObjectService.createDataFrameAnalyticsJob(jobId);
results.savedObjectsCreated[job.jobId] = { success: true };
} catch (error) {
results.savedObjectsCreated[job.jobId] = {
success: false,
error: error.body ?? error,
};
}
});
}
}
}

for (const job of status.savedObjects['anomaly-detector']) {
if (job.checks.jobExists === false) {
if (simulate === true) {
results.savedObjectsDeleted[job.jobId] = { success: true };
} else {
// Delete AD saved objects for jobs which no longer exist
const jobId = job.jobId;
tasks.push(async () => {
try {
await jobSavedObjectService.deleteAnomalyDetectionJob(jobId);
results.savedObjectsDeleted[job.jobId] = { success: true };
} catch (error) {
results.savedObjectsDeleted[job.jobId] = {
success: false,
error: error.body ?? error,
};
}
});
}
}
}
for (const job of status.savedObjects['data-frame-analytics']) {
if (job.checks.jobExists === false) {
if (simulate === true) {
results.savedObjectsDeleted[job.jobId] = { success: true };
} else {
// Delete DFA saved objects for jobs which no longer exist
const jobId = job.jobId;
tasks.push(async () => {
try {
await jobSavedObjectService.deleteDataFrameAnalyticsJob(jobId);
results.savedObjectsDeleted[job.jobId] = { success: true };
} catch (error) {
results.savedObjectsDeleted[job.jobId] = {
success: false,
error: error.body ?? error,
};
}
});
}
}
}

for (const job of status.savedObjects['anomaly-detector']) {
if (job.checks.datafeedExists === true && job.datafeedId === null) {
// add datafeed id for jobs where the datafeed exists but the id is missing from the saved object
if (simulate === true) {
results.datafeedsAdded[job.jobId] = { success: true };
} else {
const df = datafeeds.datafeeds.find((d) => d.job_id === job.jobId);
const jobId = job.jobId;
const datafeedId = df?.datafeed_id;

tasks.push(async () => {
try {
if (datafeedId !== undefined) {
await jobSavedObjectService.addDatafeed(datafeedId, jobId);
}
results.datafeedsAdded[job.jobId] = { success: true };
} catch (error) {
results.datafeedsAdded[job.jobId] = { success: false, error };
}
});
}
} else if (
job.checks.jobExists === true &&
job.checks.datafeedExists === false &&
job.datafeedId !== null &&
job.datafeedId !== undefined
) {
// remove datafeed id for jobs where the datafeed no longer exists but the id is populated in the saved object
if (simulate === true) {
results.datafeedsRemoved[job.jobId] = { success: true };
} else {
const datafeedId = job.datafeedId;
tasks.push(async () => {
try {
await jobSavedObjectService.deleteDatafeed(datafeedId);
results.datafeedsRemoved[job.jobId] = { success: true };
} catch (error) {
results.datafeedsRemoved[job.jobId] = { success: false, error: error.body ?? error };
}
});
}
}
}
await Promise.allSettled(tasks.map((t) => t()));
return results;
}

async function initSavedObjects(simulate: boolean = false, namespaces: string[] = ['*']) {
const results: { jobs: Array<{ id: string; type: string }>; success: boolean; error?: any } = {
jobs: [],
success: true,
};
const status = await checkStatus();

const jobs: JobObject[] = [];
const types: JobType[] = ['anomaly-detector', 'data-frame-analytics'];

types.forEach((type) => {
status.jobs[type].forEach((job) => {
if (job.checks.savedObjectExits === false) {
if (simulate === true) {
results.jobs.push({ id: job.jobId, type });
} else {
jobs.push({
job_id: job.jobId,
datafeed_id: job.datafeedId ?? null,
type,
});
}
}
});
});
try {
const createResults = await jobSavedObjectService.bulkCreateJobs(jobs, namespaces);
createResults.saved_objects.forEach(({ attributes }) => {
results.jobs.push({
id: attributes.job_id,
type: attributes.type,
});
});
} catch (error) {
results.success = false;
results.error = Boom.boomify(error).output;
}
return results;
}

async function _loadAllJobSavedObjects() {
const { body } = await client.asInternalUser.search<SearchResponse<SavedObjectJob>>({
index: '.kibana*',
Expand Down Expand Up @@ -388,5 +191,5 @@ export function checksFactory(
});
}

return { checkStatus, repairJobs, initSavedObjects };
return { checkStatus };
}
2 changes: 2 additions & 0 deletions x-pack/plugins/ml/server/saved_objects/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@
export { setupSavedObjects } from './saved_objects';
export { JobObject, JobSavedObjectService, jobSavedObjectServiceFactory } from './service';
export { checksFactory } from './checks';
export { repairFactory } from './repair';
export { jobInitializationFactory } from './initialization';
Loading