Skip to content

Commit

Permalink
[ML] Adding index migration warnings (#28938) (#30059)
Browse files Browse the repository at this point in the history
* [ML] Adding index migration warnings

* small refactor

* correctlng comment

* adding upgrade service to manage upgradeInProgress state

* removing missing function
  • Loading branch information
jgowdyelastic authored Feb 5, 2019
1 parent 64f26ab commit 389290e
Show file tree
Hide file tree
Showing 6 changed files with 205 additions and 99 deletions.
8 changes: 8 additions & 0 deletions x-pack/plugins/ml/public/components/upgrade/index.js
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;
* you may not use this file except in compliance with the Elastic License.
*/


export { UpgradeWarning } from './upgrade_warning';
48 changes: 48 additions & 0 deletions x-pack/plugins/ml/public/components/upgrade/upgrade_warning.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/


import React from 'react';

import {
EuiCallOut,
EuiSpacer,
} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';

import { isUpgradeInProgress } from '../../services/upgrade_service';

export function UpgradeWarning() {
if (isUpgradeInProgress() === true) {
return (
<React.Fragment>
<EuiCallOut
title={(<FormattedMessage
id="xpack.ml.upgrade.upgradeWarning.upgradeInProgressWarningTitle"
defaultMessage="Index migration in progress"
/>)}
color="warning"
iconType="alert"
>
<p>
<FormattedMessage
id="xpack.ml.upgrade.upgradeWarning.upgradeInProgressWarningDescription"
defaultMessage="Indices related to Machine Learning are currently being upgraded."
/>
<br />
<FormattedMessage
id="xpack.ml.upgrade.upgradeWarning.upgradeInProgressWarningDescriptionExtra"
defaultMessage="Some actions will not be available during this time."
/>
</p>
</EuiCallOut>
<EuiSpacer size="m" />
</React.Fragment>
);
}

return null;
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { MultiJobActions } from '../multi_job_actions';
import { NewJobButton } from '../new_job_button';
import { JobStatsBar } from '../jobs_stats_bar';
import { NodeAvailableWarning } from '../node_available_warning';
import { UpgradeWarning } from '../../../../components/upgrade';
import { RefreshJobsListButton } from '../refresh_jobs_list_button';
import { isEqual } from 'lodash';

Expand Down Expand Up @@ -390,6 +391,7 @@ export class JobsListView extends Component {
/>
<div className="job-management">
<NodeAvailableWarning />
<UpgradeWarning />
<header>
<div className="job-buttons-container">
<EuiFlexGroup alignItems="center">
Expand Down
191 changes: 105 additions & 86 deletions x-pack/plugins/ml/public/privilege/get_privileges.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@


import { ml } from 'plugins/ml/services/ml_api_service';
import { setUpgradeInProgress } from '../services/upgrade_service';

export function getPrivileges() {
const privileges = {
Expand Down Expand Up @@ -64,94 +65,20 @@ export function getPrivileges() {

ml.checkPrivilege(priv)
.then((resp) => {
// if security has been disabled, securityDisabled is returned from the endpoint
// therefore set all privileges to true
if (resp.securityDisabled) {

if(resp.upgradeInProgress === true) {
setUpgradeInProgress(true);
// only check for getting endpoints
// force all to be true if security is disabled
setGettingPrivileges(resp.cluster, privileges, (resp.securityDisabled === true));
}
else if (resp.securityDisabled) {
// if security has been disabled, securityDisabled is returned from the endpoint
// therefore set all privileges to true
Object.keys(privileges).forEach(k => privileges[k] = true);
} else {
if (resp.cluster['cluster:monitor/xpack/ml/job/get'] &&
resp.cluster['cluster:monitor/xpack/ml/job/stats/get']) {
privileges.canGetJobs = true;
}

if (resp.cluster['cluster:monitor/xpack/ml/datafeeds/get'] &&
resp.cluster['cluster:monitor/xpack/ml/datafeeds/stats/get']) {
privileges.canGetDatafeeds = true;
}

if (resp.cluster['cluster:admin/xpack/ml/job/put'] &&
resp.cluster['cluster:admin/xpack/ml/job/open'] &&
resp.cluster['cluster:admin/xpack/ml/datafeeds/put']) {
privileges.canCreateJob = true;
}

if (resp.cluster['cluster:admin/xpack/ml/job/update']) {
privileges.canUpdateJob = true;
}

if (resp.cluster['cluster:admin/xpack/ml/job/open']) {
privileges.canOpenJob = true;
}

if (resp.cluster['cluster:admin/xpack/ml/job/close']) {
privileges.canCloseJob = true;
}

if (resp.cluster['cluster:admin/xpack/ml/job/forecast']) {
privileges.canForecastJob = true;
}

if (resp.cluster['cluster:admin/xpack/ml/job/delete'] &&
resp.cluster['cluster:admin/xpack/ml/datafeeds/delete']) {
privileges.canDeleteJob = true;
}

if (resp.cluster['cluster:admin/xpack/ml/job/open'] &&
resp.cluster['cluster:admin/xpack/ml/datafeeds/start'] &&
resp.cluster['cluster:admin/xpack/ml/datafeeds/stop']) {
privileges.canStartStopDatafeed = true;
}

if (resp.cluster['cluster:admin/xpack/ml/datafeeds/update']) {
privileges.canUpdateDatafeed = true;
}

if (resp.cluster['cluster:admin/xpack/ml/datafeeds/preview']) {
privileges.canPreviewDatafeed = true;
}

if (resp.cluster['cluster:monitor/xpack/ml/calendars/get']) {
privileges.canGetCalendars = true;
}

if (resp.cluster['cluster:admin/xpack/ml/calendars/put'] &&
resp.cluster['cluster:admin/xpack/ml/calendars/jobs/update'] &&
resp.cluster['cluster:admin/xpack/ml/calendars/events/post']) {
privileges.canCreateCalendar = true;
}

if (resp.cluster['cluster:admin/xpack/ml/calendars/delete'] &&
resp.cluster['cluster:admin/xpack/ml/calendars/events/delete']) {
privileges.canDeleteCalendar = true;
}

if (resp.cluster['cluster:admin/xpack/ml/filters/get']) {
privileges.canGetFilters = true;
}

if (resp.cluster['cluster:admin/xpack/ml/filters/put'] &&
resp.cluster['cluster:admin/xpack/ml/filters/update']) {
privileges.canCreateFilter = true;
}

if (resp.cluster['cluster:admin/xpack/ml/filters/delete']) {
privileges.canDeleteFilter = true;
}

if (resp.cluster['cluster:monitor/xpack/ml/findfilestructure']) {
privileges.canFindFileStructure = true;
}

setGettingPrivileges(resp.cluster, privileges);
setActionPrivileges(resp.cluster, privileges);
}

resolve(privileges);
Expand All @@ -162,3 +89,95 @@ export function getPrivileges() {
});
}

function setGettingPrivileges(cluster = {}, privileges = {}, forceTrue = false) {
if (
forceTrue ||
(cluster['cluster:monitor/xpack/ml/job/get'] &&
cluster['cluster:monitor/xpack/ml/job/stats/get'])
) {
privileges.canGetJobs = true;
}

if (
forceTrue ||
(cluster['cluster:monitor/xpack/ml/datafeeds/get'] &&
cluster['cluster:monitor/xpack/ml/datafeeds/stats/get'])
) {
privileges.canGetDatafeeds = true;
}

if (forceTrue || cluster['cluster:monitor/xpack/ml/calendars/get']) {
privileges.canGetCalendars = true;
}

if (forceTrue || cluster['cluster:admin/xpack/ml/filters/get']) {
privileges.canGetFilters = true;
}

if (forceTrue || cluster['cluster:monitor/xpack/ml/findfilestructure']) {
privileges.canFindFileStructure = true;
}
}

function setActionPrivileges(cluster = {}, privileges = {}) {
if (cluster['cluster:admin/xpack/ml/job/put'] &&
cluster['cluster:admin/xpack/ml/job/open'] &&
cluster['cluster:admin/xpack/ml/datafeeds/put']) {
privileges.canCreateJob = true;
}

if (cluster['cluster:admin/xpack/ml/job/update']) {
privileges.canUpdateJob = true;
}

if (cluster['cluster:admin/xpack/ml/job/open']) {
privileges.canOpenJob = true;
}

if (cluster['cluster:admin/xpack/ml/job/close']) {
privileges.canCloseJob = true;
}

if (cluster['cluster:admin/xpack/ml/job/forecast']) {
privileges.canForecastJob = true;
}

if (cluster['cluster:admin/xpack/ml/job/delete'] &&
cluster['cluster:admin/xpack/ml/datafeeds/delete']) {
privileges.canDeleteJob = true;
}

if (cluster['cluster:admin/xpack/ml/job/open'] &&
cluster['cluster:admin/xpack/ml/datafeeds/start'] &&
cluster['cluster:admin/xpack/ml/datafeeds/stop']) {
privileges.canStartStopDatafeed = true;
}

if (cluster['cluster:admin/xpack/ml/datafeeds/update']) {
privileges.canUpdateDatafeed = true;
}

if (cluster['cluster:admin/xpack/ml/datafeeds/preview']) {
privileges.canPreviewDatafeed = true;
}

if (cluster['cluster:admin/xpack/ml/calendars/put'] &&
cluster['cluster:admin/xpack/ml/calendars/jobs/update'] &&
cluster['cluster:admin/xpack/ml/calendars/events/post']) {
privileges.canCreateCalendar = true;
}

if (cluster['cluster:admin/xpack/ml/calendars/delete'] &&
cluster['cluster:admin/xpack/ml/calendars/events/delete']) {
privileges.canDeleteCalendar = true;
}

if (cluster['cluster:admin/xpack/ml/filters/put'] &&
cluster['cluster:admin/xpack/ml/filters/update']) {
privileges.canCreateFilter = true;
}

if (cluster['cluster:admin/xpack/ml/filters/delete']) {
privileges.canDeleteFilter = true;
}
}
16 changes: 16 additions & 0 deletions x-pack/plugins/ml/public/services/upgrade_service.js
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;
* you may not use this file except in compliance with the Elastic License.
*/


let upgradeInProgress = false;

export function setUpgradeInProgress(show) {
upgradeInProgress = show;
}

export function isUpgradeInProgress() {
return upgradeInProgress;
}
39 changes: 26 additions & 13 deletions x-pack/plugins/ml/server/routes/system.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,20 +39,33 @@ export function systemRoutes(server, commonRouteConfig) {
server.route({
method: 'POST',
path: '/api/ml/_has_privileges',
handler(request) {
async handler(request) {
const callWithRequest = callWithRequestFactory(server, request);
// isSecurityDisabled will return true if it is a basic license
// this will cause the subsequent ml.privilegeCheck to fail.
// therefore, check for a basic license first and report that security
// is disabled because its not available on basic
if (isBasicLicense(server) || isSecurityDisabled(server)) {
// if xpack.security.enabled has been explicitly set to false
// return that security is disabled and don't call the privilegeCheck endpoint
return { securityDisabled: true };
} else {
const body = request.payload;
return callWithRequest('ml.privilegeCheck', { body })
.catch(resp => wrapError(resp));
try {
const info = await callWithRequest('ml.info');
// if ml indices are currently being migrated, upgrade_mode will be set to true
// pass this back with the privileges to allow for the disabling of UI controls.
const upgradeInProgress = (info.upgrade_mode === true);

// isSecurityDisabled will return true if it is a basic license
// this will cause the subsequent ml.privilegeCheck to fail.
// therefore, check for a basic license first and report that security
// is disabled because its not available on basic
if (isBasicLicense(server) || isSecurityDisabled(server)) {
// if xpack.security.enabled has been explicitly set to false
// return that security is disabled and don't call the privilegeCheck endpoint
return {
securityDisabled: true,
upgradeInProgress
};
} else {
const body = request.payload;
const resp = await callWithRequest('ml.privilegeCheck', { body });
resp.upgradeInProgress = upgradeInProgress;
return resp;
}
} catch (error) {
return wrapError(error);
}
},
config: {
Expand Down

0 comments on commit 389290e

Please sign in to comment.