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] Renaming saved object repair to sync #84311

Merged
merged 3 commits into from
Nov 30, 2020
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion x-pack/plugins/ml/common/types/saved_objects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export interface SavedObjectResult {
[jobId: string]: { success: boolean; error?: any };
}

export interface RepairSavedObjectResponse {
export interface SyncSavedObjectResponse {
savedObjectsCreated: SavedObjectResult;
savedObjectsDeleted: SavedObjectResult;
datafeedsAdded: SavedObjectResult;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
* you may not use this file except in compliance with the Elastic License.
*/

export { JobSpacesRepairFlyout } from './job_spaces_repair_flyout';
export { JobSpacesSyncFlyout } from './job_spaces_sync_flyout';
Original file line number Diff line number Diff line change
Expand Up @@ -23,34 +23,31 @@ import {
} from '@elastic/eui';

import { ml } from '../../services/ml_api_service';
import {
RepairSavedObjectResponse,
SavedObjectResult,
} from '../../../../common/types/saved_objects';
import { RepairList } from './repair_list';
import { SyncSavedObjectResponse, SavedObjectResult } from '../../../../common/types/saved_objects';
import { SyncList } from './sync_list';
import { useToastNotificationService } from '../../services/toast_notification_service';

interface Props {
onClose: () => void;
}
export const JobSpacesRepairFlyout: FC<Props> = ({ onClose }) => {
export const JobSpacesSyncFlyout: FC<Props> = ({ onClose }) => {
const { displayErrorToast, displaySuccessToast } = useToastNotificationService();
const [loading, setLoading] = useState(false);
const [repairable, setRepairable] = useState(false);
const [repairResp, setRepairResp] = useState<RepairSavedObjectResponse | null>(null);
const [canSync, setCanSync] = useState(false);
const [syncResp, setSyncResp] = useState<SyncSavedObjectResponse | null>(null);

async function loadRepairList(simulate: boolean = true) {
async function loadSyncList(simulate: boolean = true) {
setLoading(true);
try {
const resp = await ml.savedObjects.repairSavedObjects(simulate);
setRepairResp(resp);
const resp = await ml.savedObjects.syncSavedObjects(simulate);
setSyncResp(resp);

const count = Object.values(resp).reduce((acc, cur) => acc + Object.keys(cur).length, 0);
setRepairable(count > 0);
setCanSync(count > 0);
setLoading(false);
return resp;
} catch (error) {
// this shouldn't be hit as errors are returned per-repair task
// this shouldn't be hit as errors are returned per-sync task
// as part of the response
displayErrorToast(error);
setLoading(false);
Expand All @@ -59,32 +56,33 @@ export const JobSpacesRepairFlyout: FC<Props> = ({ onClose }) => {
}

useEffect(() => {
loadRepairList();
loadSyncList();
}, []);

async function repair() {
if (repairable) {
// perform the repair
const resp = await loadRepairList(false);
// check simulate the repair again to check that all
// items have been repaired.
await loadRepairList(true);
async function sync() {
if (canSync) {
// perform the sync
const resp = await loadSyncList(false);
// check simulate the sync again to check that all
// items have been synchronized.
await loadSyncList(true);

if (resp === null) {
return;
}
const { successCount, errorCount } = getResponseCounts(resp);
if (errorCount > 0) {
const title = i18n.translate('xpack.ml.management.repairSavedObjectsFlyout.repair.error', {
defaultMessage: 'Some jobs cannot be repaired.',
const title = i18n.translate('xpack.ml.management.syncSavedObjectsFlyout.sync.error', {
defaultMessage: 'Some jobs cannot be synchronized.',
});
displayErrorToast(resp as any, title);
return;
}

displaySuccessToast(
i18n.translate('xpack.ml.management.repairSavedObjectsFlyout.repair.success', {
defaultMessage: '{successCount} {successCount, plural, one {job} other {jobs}} repaired',
i18n.translate('xpack.ml.management.syncSavedObjectsFlyout.sync.success', {
defaultMessage:
'{successCount} {successCount, plural, one {job} other {jobs}} synchronized',
values: { successCount },
})
);
Expand All @@ -98,8 +96,8 @@ export const JobSpacesRepairFlyout: FC<Props> = ({ onClose }) => {
<EuiTitle size="m">
<h2>
<FormattedMessage
id="xpack.ml.management.repairSavedObjectsFlyout.headerLabel"
defaultMessage="Repair saved objects"
id="xpack.ml.management.syncSavedObjectsFlyout.headerLabel"
defaultMessage="Synchronize saved objects"
/>
</h2>
</EuiTitle>
Expand All @@ -108,33 +106,29 @@ export const JobSpacesRepairFlyout: FC<Props> = ({ onClose }) => {
<EuiCallOut color="primary">
<EuiText size="s">
<FormattedMessage
id="xpack.ml.management.repairSavedObjectsFlyout.description"
defaultMessage="Repair the saved objects if they are out of sync with the machine learning jobs in Elasticsearch."
id="xpack.ml.management.syncSavedObjectsFlyout.description"
defaultMessage="Synchronize the saved objects if they are out of sync with the machine learning jobs in Elasticsearch."
/>
</EuiText>
</EuiCallOut>
<EuiSpacer />
<RepairList repairItems={repairResp} />
<SyncList syncItems={syncResp} />
</EuiFlyoutBody>
<EuiFlyoutFooter>
<EuiFlexGroup justifyContent="spaceBetween">
<EuiFlexItem grow={false}>
<EuiButtonEmpty iconType="cross" onClick={onClose} flush="left">
<FormattedMessage
id="xpack.ml.management.repairSavedObjectsFlyout.closeButton"
id="xpack.ml.management.syncSavedObjectsFlyout.closeButton"
defaultMessage="Close"
/>
</EuiButtonEmpty>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton
onClick={repair}
fill
isDisabled={repairable === false || loading === true}
>
<EuiButton onClick={sync} fill isDisabled={canSync === false || loading === true}>
<FormattedMessage
id="xpack.ml.management.repairSavedObjectsFlyout.repairButton"
defaultMessage="Repair"
id="xpack.ml.management.syncSavedObjectsFlyout.syncButton"
defaultMessage="Synchronize"
/>
</EuiButton>
</EuiFlexItem>
Expand All @@ -145,7 +139,7 @@ export const JobSpacesRepairFlyout: FC<Props> = ({ onClose }) => {
);
};

function getResponseCounts(resp: RepairSavedObjectResponse) {
function getResponseCounts(resp: SyncSavedObjectResponse) {
let successCount = 0;
let errorCount = 0;
Object.values(resp).forEach((result: SavedObjectResult) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,46 +9,44 @@ import { FormattedMessage } from '@kbn/i18n/react';

import { EuiText, EuiTitle, EuiAccordion, EuiTextColor, EuiHorizontalRule } from '@elastic/eui';

import { RepairSavedObjectResponse } from '../../../../common/types/saved_objects';
import { SyncSavedObjectResponse } from '../../../../common/types/saved_objects';

export const RepairList: FC<{ repairItems: RepairSavedObjectResponse | null }> = ({
repairItems,
}) => {
if (repairItems === null) {
export const SyncList: FC<{ syncItems: SyncSavedObjectResponse | null }> = ({ syncItems }) => {
if (syncItems === null) {
return null;
}

return (
<>
<SavedObjectsCreated repairItems={repairItems} />
<SavedObjectsCreated syncItems={syncItems} />

<EuiHorizontalRule margin="l" />

<SavedObjectsDeleted repairItems={repairItems} />
<SavedObjectsDeleted syncItems={syncItems} />

<EuiHorizontalRule margin="l" />

<DatafeedsAdded repairItems={repairItems} />
<DatafeedsAdded syncItems={syncItems} />

<EuiHorizontalRule margin="l" />

<DatafeedsRemoved repairItems={repairItems} />
<DatafeedsRemoved syncItems={syncItems} />

<EuiHorizontalRule margin="l" />
</>
);
};

const SavedObjectsCreated: FC<{ repairItems: RepairSavedObjectResponse }> = ({ repairItems }) => {
const items = Object.keys(repairItems.savedObjectsCreated);
const SavedObjectsCreated: FC<{ syncItems: SyncSavedObjectResponse }> = ({ syncItems }) => {
const items = Object.keys(syncItems.savedObjectsCreated);

const title = (
<>
<EuiTitle size="xs">
<h3>
<EuiTextColor color={items.length ? 'default' : 'subdued'}>
<FormattedMessage
id="xpack.ml.management.repairSavedObjectsFlyout.savedObjectsCreated.title"
id="xpack.ml.management.syncSavedObjectsFlyout.savedObjectsCreated.title"
defaultMessage="Missing saved objects ({count})"
values={{ count: items.length }}
/>
Expand All @@ -59,27 +57,27 @@ const SavedObjectsCreated: FC<{ repairItems: RepairSavedObjectResponse }> = ({ r
<p>
<EuiTextColor color="subdued">
<FormattedMessage
id="xpack.ml.management.repairSavedObjectsFlyout.savedObjectsCreated.description"
id="xpack.ml.management.syncSavedObjectsFlyout.savedObjectsCreated.description"
defaultMessage="If there are jobs that do not have accompanying saved objects, they will be created in the current space."
/>
</EuiTextColor>
</p>
</EuiText>
</>
);
return <RepairItem id="savedObjectsCreated" title={title} items={items} />;
return <SyncItem id="savedObjectsCreated" title={title} items={items} />;
};

const SavedObjectsDeleted: FC<{ repairItems: RepairSavedObjectResponse }> = ({ repairItems }) => {
const items = Object.keys(repairItems.savedObjectsDeleted);
const SavedObjectsDeleted: FC<{ syncItems: SyncSavedObjectResponse }> = ({ syncItems }) => {
const items = Object.keys(syncItems.savedObjectsDeleted);

const title = (
<>
<EuiTitle size="xs">
<h3>
<EuiTextColor color={items.length ? 'default' : 'subdued'}>
<FormattedMessage
id="xpack.ml.management.repairSavedObjectsFlyout.savedObjectsDeleted.title"
id="xpack.ml.management.syncSavedObjectsFlyout.savedObjectsDeleted.title"
defaultMessage="Unmatched saved objects ({count})"
values={{ count: items.length }}
/>
Expand All @@ -90,27 +88,27 @@ const SavedObjectsDeleted: FC<{ repairItems: RepairSavedObjectResponse }> = ({ r
<p>
<EuiTextColor color="subdued">
<FormattedMessage
id="xpack.ml.management.repairSavedObjectsFlyout.savedObjectsDeleted.description"
id="xpack.ml.management.syncSavedObjectsFlyout.savedObjectsDeleted.description"
defaultMessage="If there are saved objects that do not have an accompanying job, they will be deleted."
/>
</EuiTextColor>
</p>
</EuiText>
</>
);
return <RepairItem id="savedObjectsDeleted" title={title} items={items} />;
return <SyncItem id="savedObjectsDeleted" title={title} items={items} />;
};

const DatafeedsAdded: FC<{ repairItems: RepairSavedObjectResponse }> = ({ repairItems }) => {
const items = Object.keys(repairItems.datafeedsAdded);
const DatafeedsAdded: FC<{ syncItems: SyncSavedObjectResponse }> = ({ syncItems }) => {
const items = Object.keys(syncItems.datafeedsAdded);

const title = (
<>
<EuiTitle size="xs">
<h3>
<EuiTextColor color={items.length ? 'default' : 'subdued'}>
<FormattedMessage
id="xpack.ml.management.repairSavedObjectsFlyout.datafeedsAdded.title"
id="xpack.ml.management.syncSavedObjectsFlyout.datafeedsAdded.title"
defaultMessage="Saved objects with missing datafeeds ({count})"
values={{ count: items.length }}
/>
Expand All @@ -121,27 +119,27 @@ const DatafeedsAdded: FC<{ repairItems: RepairSavedObjectResponse }> = ({ repair
<p>
<EuiTextColor color="subdued">
<FormattedMessage
id="xpack.ml.management.repairSavedObjectsFlyout.datafeedsAdded.description"
id="xpack.ml.management.syncSavedObjectsFlyout.datafeedsAdded.description"
defaultMessage="If there are saved objects that are missing the datafeed ID for anomaly detection jobs, the ID will be added."
/>
</EuiTextColor>
</p>
</EuiText>
</>
);
return <RepairItem id="datafeedsAdded" title={title} items={items} />;
return <SyncItem id="datafeedsAdded" title={title} items={items} />;
};

const DatafeedsRemoved: FC<{ repairItems: RepairSavedObjectResponse }> = ({ repairItems }) => {
const items = Object.keys(repairItems.datafeedsRemoved);
const DatafeedsRemoved: FC<{ syncItems: SyncSavedObjectResponse }> = ({ syncItems }) => {
const items = Object.keys(syncItems.datafeedsRemoved);

const title = (
<>
<EuiTitle size="xs">
<h3>
<EuiTextColor color={items.length ? 'default' : 'subdued'}>
<FormattedMessage
id="xpack.ml.management.repairSavedObjectsFlyout.datafeedsRemoved.title"
id="xpack.ml.management.syncSavedObjectsFlyout.datafeedsRemoved.title"
defaultMessage="Saved objects with unmatched datafeed IDs ({count})"
values={{ count: items.length }}
/>
Expand All @@ -152,31 +150,29 @@ const DatafeedsRemoved: FC<{ repairItems: RepairSavedObjectResponse }> = ({ repa
<p>
<EuiTextColor color="subdued">
<FormattedMessage
id="xpack.ml.management.repairSavedObjectsFlyout.datafeedsRemoved.description"
id="xpack.ml.management.syncSavedObjectsFlyout.datafeedsRemoved.description"
defaultMessage="If there are saved objects that use a datafeed that does not exist, they will be deleted."
/>
</EuiTextColor>
</p>
</EuiText>
</>
);
return <RepairItem id="datafeedsRemoved" title={title} items={items} />;
return <SyncItem id="datafeedsRemoved" title={title} items={items} />;
};

const RepairItem: FC<{ id: string; title: JSX.Element; items: string[] }> = ({
const SyncItem: FC<{ id: string; title: JSX.Element; items: string[] }> = ({
id,
title,
items,
}) => (
<EuiAccordion id={id} buttonContent={title} paddingSize="l">
<EuiText size="s">
{items.length && (
<ul>
{items.map((item) => (
<li key={item}>{item}</li>
))}
</ul>
)}
<ul>
{items.map((item) => (
<li key={item}>{item}</li>
))}
</ul>
</EuiText>
</EuiAccordion>
);
Loading