diff --git a/packages/osd-opensearch/package.json b/packages/osd-opensearch/package.json index 02fcddb36e6f..44404a9ae5a3 100644 --- a/packages/osd-opensearch/package.json +++ b/packages/osd-opensearch/package.json @@ -12,7 +12,7 @@ "osd:watch": "../../scripts/use_node scripts/build --watch" }, "dependencies": { - "@opensearch-project/opensearch": "^2.1.0", + "@opensearch-project/opensearch": "^2.2.0", "@osd/dev-utils": "1.0.0", "abort-controller": "^3.0.0", "chalk": "^4.1.0", diff --git a/src/plugins/point_in_time_management/public/components/breadcrumbs.ts b/src/plugins/point_in_time_management/public/components/breadcrumbs.ts index c20af07652b9..b5bd41852f88 100644 --- a/src/plugins/point_in_time_management/public/components/breadcrumbs.ts +++ b/src/plugins/point_in_time_management/public/components/breadcrumbs.ts @@ -1,17 +1,29 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { i18n } from '@osd/i18n'; - -export function getListBreadcrumbs() { - return [ - { - text: i18n.translate('pitManagement.listBreadcrumb', { - defaultMessage: 'Point in time', - }), - href: `/`, - }, - ]; -} +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { i18n } from '@osd/i18n'; + +export function getListBreadcrumbs() { + return [ + { + text: i18n.translate('pitManagement.listBreadcrumb', { + defaultMessage: 'Point in time', + }), + href: `/`, + }, + ]; +} + +export function getEditBreadcrumbs() { + return [ + ...getListBreadcrumbs(), + { + text: i18n.translate('dataSourcesManagement.dataSources.createBreadcrumb', { + defaultMessage: 'Edit', + }), + href: `/edit`, + }, + ]; +} diff --git a/src/plugins/point_in_time_management/public/components/pit_edit/edit_page.tsx b/src/plugins/point_in_time_management/public/components/pit_edit/edit_page.tsx new file mode 100644 index 000000000000..f4cdcae867cd --- /dev/null +++ b/src/plugins/point_in_time_management/public/components/pit_edit/edit_page.tsx @@ -0,0 +1,124 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import React, { useEffect, useState } from 'react'; +import { RouteComponentProps, withRouter } from 'react-router-dom'; +import { useEffectOnce, useMount } from 'react-use'; +import { i18n } from '@osd/i18n'; +import { + EuiBottomBar, + EuiButton, + EuiButtonEmpty, + EuiCheckbox, + EuiDescribedFormGroup, + EuiFieldNumber, + EuiFieldText, + EuiFlexGroup, + EuiFlexItem, + EuiForm, + EuiFormRow, + EuiPageContent, + EuiPageHeader, + EuiPageHeaderSection, + EuiSpacer, + EuiTitle, +} from '@elastic/eui'; +import { useOpenSearchDashboards } from '../../../../opensearch_dashboards_react/public'; +import { PointInTimeAttributes, PointInTimeManagementContext } from '../../types'; +import { getEditBreadcrumbs } from '../breadcrumbs'; +import { EditPitForm } from './edit_pit_form'; +import { + findById, + findPointInTimeSavedObject, + updatePointInTimeById, + updatePointInTimeKeepAlive, +} from '../utils'; +import { ToastMessageItem } from '../../../../data_source_management/public/types'; +import { getServices, Services } from '../../services'; + +const defaultPitSavedObject: PointInTimeAttributes = { + pit_id: '', + creation_time: 0, + id: '', + keepAlive: 0, + name: '', + addtime: 0, + delete_on_expiry: false, +}; + +export const PITEdit: React.FunctionComponent> = ( + props: RouteComponentProps<{ id: string }> +) => { + const { + setBreadcrumbs, + savedObjects, + notifications: { toasts }, + http, + } = useOpenSearchDashboards().services; + const PitID: string = props.match.params.id; + const [pitSavedObject, setPitSavedObject] = useState( + defaultPitSavedObject + ); + const [isLoading, setIsLoading] = useState(false); + const [newProp, setNewProp] = useState(false); + const services: Services = getServices(http); + useEffectOnce(() => { + console.log(PitID); + setBreadcrumbs(getEditBreadcrumbs()); + setIsLoading(true); + (async function () { + await fetchPitSavedObject(); + })(); + }); + + const fetchPitSavedObject = async () => { + const tempPitSavedObject = await findById(savedObjects.client, PitID); + setNewProp(true); + const pointInTimeAttributes: PointInTimeAttributes = { + creation_time: tempPitSavedObject.attributes.creation_time, + name: tempPitSavedObject.attributes.name, + keepAlive: tempPitSavedObject.attributes.keepAlive, + pit_id: tempPitSavedObject.attributes.pit_id, + id: tempPitSavedObject.id, + addtime: 0, + delete_on_expiry: tempPitSavedObject.attributes.delete_on_expiry, + }; + console.log('This is teh attributes'); + console.log(pointInTimeAttributes); + setPitSavedObject(pointInTimeAttributes); + setIsLoading(false); + }; + + const handleSubmit = async (attributes: PointInTimeAttributes) => { + console.log('These are the attributes', attributes); + const new_keep_alive_proposal = attributes.addtime.toString() + 'm'; + console.log(attributes.pit_id, new_keep_alive_proposal); + await services.addPitTime(attributes.pit_id, new_keep_alive_proposal); + await updatePointInTimeById(savedObjects.client, attributes.id, attributes); + }; + + const handleDisplayToastMessage = ({ id, defaultMessage, success }: ToastMessageItem) => { + if (success) { + toasts.addSuccess(i18n.translate(id, { defaultMessage })); + } else { + toasts.addWarning(i18n.translate(id, { defaultMessage })); + } + }; + + return ( + <> + {!isLoading ? ( + + ) : null} + + ); +}; + +export const PITEditWithRouter = withRouter(PITEdit); diff --git a/src/plugins/point_in_time_management/public/components/pit_edit/edit_pit_form.tsx b/src/plugins/point_in_time_management/public/components/pit_edit/edit_pit_form.tsx new file mode 100644 index 000000000000..58d8f5bb0364 --- /dev/null +++ b/src/plugins/point_in_time_management/public/components/pit_edit/edit_pit_form.tsx @@ -0,0 +1,347 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ +import React from 'react'; +import { + EuiBottomBar, + EuiButton, + EuiButtonEmpty, + EuiCheckbox, + EuiDescribedFormGroup, + EuiFieldNumber, + EuiFieldText, + EuiFlexGroup, + EuiFlexItem, + EuiForm, + EuiFormRow, + EuiPageContent, + EuiPageHeader, + EuiPageHeaderSection, + EuiSpacer, + EuiTitle, +} from '@elastic/eui'; +import { i18n } from '@osd/i18n'; +import { PointInTimeAttributes, ToastMessageItem } from '../../types'; +import { findById } from '../utils'; + +export interface EditPitProps { + existingPointInTime: PointInTimeAttributes; + handleSubmit: (formValues: PointInTimeAttributes) => void; + displayToastMessage: (info: ToastMessageItem) => void; + newProp: boolean; +} + +export interface EditPitState { + keepAlive: number; + name: string; + pit_id?: string; + id?: string; + delete_pit: boolean; + showUpdateOptions: boolean; + isLoading: boolean; + checked: boolean; + AddTimeHr: any; + AddTimeMin: any; + addTime: any; +} + +export class EditPitForm extends React.Component { + constructor(props: EditPitProps, context: EditPitState) { + super(props, context); + this.state = { + keepAlive: 0, + name: '', + pit_id: '', + id: '', + delete_pit: false, + showUpdateOptions: false, + isLoading: false, + checked: false, + AddTimeHr: 0, + AddTimeMin: 0, + addTime: 0, + }; + } + + componentDidMount() { + this.setFormValuesForEditMode(); + console.log('These are the props in mount'); + console.log(this.props); + } + + resetFormValues = () => { + this.setFormValuesForEditMode(); + this.setState({ showUpdateOptions: false }); + }; + + setFormValuesForEditMode() { + if (this.props.existingPointInTime) { + const { keepAlive, name, pit_id, id, addtime } = this.props.existingPointInTime; + this.setState({ + keepAlive, + name, + pit_id, + id, + addtime, + }); + } + } + + onChangeName = (e: { target: { value: any } }) => { + this.setState({ name: e.target.value }); + }; + + onChangeKeepAlive = (e: { target: { value: any } }) => { + this.setState({ name: e.target.value }); + }; + + isFormValid = (): boolean => { + console.log('This is the form validation'); + return true; + }; + + onClickUpdatePit = async () => { + if (this.isFormValid()) { + const formValues: PointInTimeAttributes = { + name: this.state.name, + keepAlive: this.state.keepAlive, + creation_time: this.state.keepAlive, + id: this.state.id, + pit_id: this.state.pit_id, + addtime: this.state.addTime, + delete_on_expiry: this.state.checked, + }; + this.setState({ isLoading: true }); + + try { + console.log('OnClickUpdate', formValues); + await this.props.handleSubmit(formValues); + this.setState({ showUpdateOptions: false }); + this.setFormValuesForEditMode(); + } catch (e) { + this.props.displayToastMessage({ + id: 'PointInTimeManagement.editPointInTime.editPointInTimeFailMsg', + defaultMessage: 'Updating the Point in time failed with some errors.', + }); + } finally { + this.setState({ isLoading: false }); + } + } + }; + + onChange = (e) => { + this.setState({ checked: e.target.checked }); + }; + + didFormValuesChange = () => { + const formValues: PointInTimeAttributes = { + name: this.state.name, + pit_id: this.state.pit_id, + keepAlive: this.state.keepAlive, + id: this.state.id, + addtime: this.state.addTime, + delete_on_expiry: this.state.checked, + }; + + const { keepAlive, name, pit_id, id, delete_on_expiry } = this.props.existingPointInTime; + + const isNameChanged: boolean = formValues.name !== name; + const isAddTimeChanged: boolean = formValues.addtime > 0; + const isDeleteOnExpirtChanged: boolean = formValues.delete_on_expiry !== delete_on_expiry; + if (isNameChanged || isAddTimeChanged || isDeleteOnExpirtChanged) { + this.setState({ showUpdateOptions: true }); + } else { + this.setState({ showUpdateOptions: false }); + } + }; + + onChangeFormValues = () => { + setTimeout(() => { + this.didFormValuesChange(); + }, 0); + }; + + onChangeTimeHr = (e: { target: { value: any } }) => { + this.setState({ + AddTimeHr: parseInt(e.target.value), + addTime: 60 * parseInt(e.target.value) + this.state.AddTimeMin, + }); + console.log(this.state); + }; + + onChangeTimeMin = (e: { target: { value: any } }) => { + this.setState({ + AddTimeMin: parseInt(e.target.value), + addTime: 60 * this.state.AddTimeHr + parseInt(e.target.value), + }); + console.log(this.state); + }; + + onChangePitName = (e: { target: { value: any } }) => { + this.setState({ name: e.target.value }); + console.log(e.target.value); + }; + + onChangeDeleteObject = (e) => { + this.setState({ checked: e.target.checked }); + console.log(this.state.checked); + }; + + renderBottomBar = () => { + return ( + + + + + + this.resetFormValues()} + aria-describedby="aria-describedby.countOfUnsavedSettings" + data-test-subj="pit-edit-cancelButton" + > + Discard changes + + + + + Save changes + + + + + ); + }; + + render() { + return ( + <> + + + + +

Time Configurations

+
+
+
+ + this.onChangeFormValues()} + data-test-subj="pit-edit" + > + Add time} + description={ +

+ The keep_alive time is the amount of time the PIT is kept active. The time entered + will also be the amount of time a PIT is extended by when it is queried. A PITs + time can not be extended by an amount less than the one entered. The keep alive + time can not exceed a maximum of X hours. +

+ } + > + + + + + + + + + + +
+
+
+ + + + + +

Dashboard PIT configurations

+
+
+
+ + this.onChangeFormValues()} + data-test-subj="pit-edit-2" + > + PIT name} + description={ +

Choose a name for a PIT that is available in OpenSearch Dashboards.

+ } + > + + + +
+ Post-expiration actions} + description={ +

+ PIT data is lost once it expires you have the option to keep the PIT metadata + after after expiration. expiration. expiration. expiration. expiration. You can + also choose to keep the Dashboard Object expiration. This object will be converted + to an Index Pattern and Pattern and it will reference data. +

+ } + > + + <> + + this.onChange(e)} + disabled={true} + /> + + +
+
+ {this.state.showUpdateOptions ? this.renderBottomBar() : null} +
+ + ); + } +} diff --git a/src/plugins/point_in_time_management/public/components/pit_edit/index.ts b/src/plugins/point_in_time_management/public/components/pit_edit/index.ts new file mode 100644 index 000000000000..7a6f6aca2ee3 --- /dev/null +++ b/src/plugins/point_in_time_management/public/components/pit_edit/index.ts @@ -0,0 +1,6 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +export { PITEditWithRouter } from './edit_page'; diff --git a/src/plugins/point_in_time_management/public/components/pit_table/pit_table.tsx b/src/plugins/point_in_time_management/public/components/pit_table/pit_table.tsx index 7c8425b224f0..821784d946f4 100644 --- a/src/plugins/point_in_time_management/public/components/pit_table/pit_table.tsx +++ b/src/plugins/point_in_time_management/public/components/pit_table/pit_table.tsx @@ -1,715 +1,715 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useEffect, useState } from 'react'; -import { RouteComponentProps, withRouter } from 'react-router-dom'; -import { useEffectOnce, useMount } from 'react-use'; -import { - EuiButton, - EuiInMemoryTable, - EuiPageContent, - EuiPageContentBody, - EuiSpacer, - EuiSearchBarProps, - Query, - EuiPageContentHeader, - EuiPageContentHeaderSection, - EuiTitle, - EuiText, - EuiFlexGroup, - EuiFlexItem, - EuiBadge, - EuiSelect, - EuiConfirmModal, - EuiFormRow, - EuiFieldText, -} from '@elastic/eui'; -import { i18n } from '@osd/i18n'; -import { FormattedMessage } from '@osd/i18n/react'; -import moment, { now } from 'moment'; -import { SavedObjectReference } from 'src/core/public'; -import { getListBreadcrumbs } from '../breadcrumbs'; -import { PointInTimeManagementContext } from '../../types'; -import { useOpenSearchDashboards } from '../../../../opensearch_dashboards_react/public'; -import { - getDataSources, - PointInTime, - createSavedObject, - getSavedPits, - deletePointInTimeById, - updatePointInTimeSavedObject, -} from '../utils'; -import { EmptyState, NoDataSourceState } from './empty_state'; -// import { PageHeader } from './page_header'; -import { getServices, Services } from '../../services'; -import { PointInTimeCreateForm } from '../create_pit'; -import { CreateButton } from '../create_button'; -// import { dataSource } from 'src/plugins/data_source/server/saved_objects'; - -export interface DataSourceItem { - id: string; - name: string; - title: string; - sort: string; -} - -export interface DashboardPitItem { - id: string; - name: string; - creation_time: number; - keep_alive: number; - delete_on_expiry: boolean; -} - -export interface PitItem { - pit_id: string; - name: string; - creation_time: number; - keep_alive: number; - dataSource: string; - expiry: number; -} - -const PITTable = ({ history }: RouteComponentProps) => { - const { - setBreadcrumbs, - savedObjects, - notifications: { toasts }, - http, - } = useOpenSearchDashboards().services; - - useMount(() => { - setBreadcrumbs(getListBreadcrumbs()); - }); - - const createButton = ; - - - const services: Services = getServices(http); - - // TODO: update this for cases when some data source name is default - const defaultDataSource: DataSourceItem = { id: '', title: '', sort: '0', name: 'default' }; - - // TODO: use APIs to fetch PITs and update the table and message - const [loading, setLoading] = useState(false); - const [pits, setPits] = useState([]); - const [pitsToDelete, setPitsToDelete] = useState([]); - const [selectedPits, setSelectedPits] = useState([]); - // const [dashboardPits, setDashboardPits] = useState([]); - const [message, setMessage] = useState(); - - const [dataSources, setDataSources] = useState([defaultDataSource]); - const [dataSource, setDataSource] = useState(''); - const [isModalVisible, setIsModalVisible] = useState(false); - - useEffectOnce(() => { - fetchDataSources(); - }); - - useEffect(() => { - getPits(dataSource); - }, [dataSource]); - - const fetchDataSources = () => { - getDataSources(savedObjects.client) - .then((fetchedDataSources) => { - if (fetchedDataSources?.length) { - setDataSources( - fetchedDataSources - .concat([defaultDataSource]) - .sort((a, b) => a.sort.localeCompare(b.sort)) - ); - } - }) - .catch(() => { - toasts.addDanger( - i18n.translate('pitManagement.pitTable.fetchDataSourceError', { - defaultMessage: 'Unable to find existing data sources', - }) - ); - }); - }; - - const navigateEdit = (pit) => { - console.log(pit); - history.push(`${pit.id}`); - }; - - const getPits = (dataSourceId?: string) => { - // setMessage(<>Loading PITs...); - setLoading(true); - console.log(dataSourceId); - // let dataSourceId: string | undefined; - const dataSourceName = dataSourceId; - if (dataSourceId === '') { - dataSourceId = undefined; - } else if (dataSourceId === 'noDataSource') { - // setMessage(); - setLoading(false); - setPits([]); - return; - } else { - const dataSource = dataSources.filter((x) => x.title === dataSourceId); - if (dataSource.length === 0) { - toasts.addDanger( - i18n.translate('pitManagement.pitTable.fetchDataSourceError', { - defaultMessage: 'Unable to find data source', - }) - ); - setMessage(); - setPits([]); - return; - } else { - dataSourceId = dataSource[0].id; - } - } - setMessage(); - console.log(dataSourceId); - - services - .getAllPits(dataSourceId) - .then((fetchedPits) => { - getSavedPits(savedObjects.client) - .then((fetchedDashboardPits) => { - // if (fetchedDataSources?.length) { - // setDashboardPits(fetchedDataSources); - // } - console.log('dashboard pits', fetchedDashboardPits); - setLoading(false); - if (fetchedPits?.resp?.pits) { - const expiredPits: DashboardPitItem[] = []; - // if (dataSourceId === undefined) { - // expiredPits = fetchedDashboardPits.filter( - // (x) => !fetchedPits?.resp?.pits.some((x2) => x.attributes.id === x2.pit_id) - // ); - // } - // console.log('expired', expiredPits); - // expiredPits.filter(x=>x.attributes.delete_on_expiry).forEach(x=> { - // console.log('deleting ', x) - // deletePointInTimeById(savedObjects.client, x.id); - // }) - - if (dataSourceId === undefined) { - fetchedDashboardPits.forEach((x) => { - if (!fetchedPits?.resp?.pits.some((x2) => x.attributes.pit_id === x2.pit_id)) { - if (x.attributes.delete_on_expiry) { - console.log('deleting ', x); - deletePointInTimeById(savedObjects.client, x.id); - } else { - expiredPits.push(x); - } - } - }); - } - console.log('expired', expiredPits); - - setPits( - fetchedPits?.resp?.pits - .map((val) => { - const date = moment(val.creation_time); - const formattedDate = date.format('MMM D @ HH:mm:ss'); - const expiry = val.creation_time + val.keep_alive; - const dashboardPit = fetchedDashboardPits.filter( - (x) => x.attributes.pit_id === val.pit_id - ); - if (dashboardPit.length > 0) { - console.log(dashboardPit); - dashboardPit[0].attributes.keepAlive = val.keep_alive; - console.log('updating', dashboardPit); - updatePointInTimeSavedObject( - savedObjects.client, - dashboardPit[0].id, - dashboardPit[0].attributes, - dashboardPit[0].references - ); - return { - pit_id: val.pit_id, - id: dashboardPit[0].id, - name: dashboardPit[0].attributes.name, - creation_time: val.creation_time, - keep_alive: val.keep_alive, - dataSource: dataSourceName, - isSavedObject: true, - expiry, - }; - } - return { - pit_id: val.pit_id, - id: val.id, - name: formattedDate, - creation_time: val.creation_time, - keep_alive: val.keep_alive, - dataSource: dataSourceName, - isSavedObject: false, - expiry, - }; - }) - .concat( - expiredPits.map((x) => ({ - pit_id: x.attributes.pit_id, - name: x.attributes.name, - id: x.id, - creation_time: x.attributes.creation_time, - keep_alive: x.attributes.keepAlive, - dataSource: dataSourceName, - isSavedObject: true, - expiry: x.attributes.creation_time + x.attributes.keepAlive, - })) - ) - ); - } - - console.log(fetchedPits?.resp?.pits as PitItem[]); - console.log(pits.length); - }) - .catch(() => { - toasts.addDanger( - i18n.translate('pitManagement.pitTable.fetchPitError', { - defaultMessage: 'Unable to load existing dashboard PITs', - }) - ); - }); - }) - .catch(() => { - setLoading(false); - toasts.addDanger( - i18n.translate('pitManagement.pitTable.fetchDataSourceError', { - defaultMessage: 'Unable to fetch point in time objects.', - }) - ); - }); - }; - - const createPointInTime = () => { - // setIsFlyoutVisible(false); - const pit: PointInTime = { - pit_id: - 'o463QQEKbXktaW5kZXgtMRZqUlZFU2lSaFE1eUx0cHdiSjNLWjRRABZtWjNCdk1ZdFRZbS1JbnltaVlBTWdBAAAAAAAAAACGFlJXLVVNYXVQVFctQVIxVmh1OUJuSlEBFmpSVkVTaVJoUTV5THRwd2JKM0taNFEAAA==', - keepAlive: 30000000, - creation_time: 1684418768188, - name: 'PIT-my-index-1223', // Todo create pit and fill the pit id - delete_on_expiry: false, - }; - - const reference: SavedObjectReference = { - id: '5586e600-f57b-11ed-90e3-a75eeb2a18a5', - type: 'index-pattern', - name: 'my*', - }; - createSavedObject(pit, savedObjects.client, reference); - }; - - const getBackendPits = () => { - getSavedPits(savedObjects.client).then((fetchedDashboardPits) => { - console.log(fetchedDashboardPits); - }); - }; - - const deletePit = (pit) => { - let dataSourceId: string | undefined = ''; - if (dataSource === '') { - dataSourceId = undefined; - } else { - const dataSourceObj = dataSources.filter((x) => x.title === dataSource); - if (dataSourceObj.length === 0) { - toasts.addDanger( - i18n.translate('pitManagement.pitTable.fetchDataSourceError', { - defaultMessage: 'Unable to find data source', - }) - ); - setMessage(); - setPits([]); - return; - } else { - dataSourceId = dataSourceObj[0].id; - } - } - services.deletePits([pit.pit_id], dataSourceId).then((deletedPits) => { - console.log(deletedPits); - getPits(dataSource); - }); - }; - - const DeleteModal = ({}) => { - const closeModal = () => { - setIsModalVisible(false); - }; - - const [value, setValue] = useState(''); - const onChange = (e) => { - setValue(e.target.value); - console.log(pitsToDelete[0]); - }; - - let modal; - - if (isModalVisible) { - const expired = moment(pitsToDelete[0].expiry).isBefore(now()); - if (expired) { - modal = ( - { - closeModal(); - deletePit(pitsToDelete[0]); - setPitsToDelete([]); - }} - confirmButtonText="Delete PIT" - cancelButtonText="Cancel" - buttonColor="danger" - > - The PIT will be permanently deleted. This action is irreversible. - - - ); - } else { - modal = ( - { - closeModal(); - deletePit(pitsToDelete[0]); - setPitsToDelete([]); - }} - confirmButtonText="Delete PIT" - cancelButtonText="Cancel" - buttonColor="danger" - confirmButtonDisabled={value !== pitsToDelete[0].name} - > - - This is an active PIT. Deleting it will permanently remove data and may cause - unexpected behavior in saved objects that use this PIT. This action is irreversible. - - - - - - - ); - } - } - - return
{modal}
; - }; - - const displayDelete = (pit) => { - setPitsToDelete([pit]); - setIsModalVisible(true); - }; - - const actions = [ - { - name: 'Add Time', - description: 'Add Time', - icon: 'clock', - type: 'icon', - onClick: fetchDataSources, - }, - { - name: 'Configure PIT', - description: 'Configure PIT', - icon: 'pencil', - type: 'icon', - onClick: navigateEdit, // route it to edit page --> create a route page - }, - { - name: 'Delete', - description: 'Delete PIT', - icon: 'trash', - type: 'icon', - color: 'danger', - onClick: displayDelete, - }, - ]; - - const Timer = ({ endTime }) => { - const getTime = () => - moment(endTime).isBefore(now()) ? 'Expired' : '~ ' + moment(endTime).fromNow(true); - - const getBadgeColor = () => { - const timeLeft = endTime - moment.now().valueOf(); - if (timeLeft < 0) { - return 'hollow'; - } else if (timeLeft < 10 * 60 * 1000) { - return 'danger'; - } else { - return 'default'; - } - }; - - const [time, setTime] = useState(() => getTime()); - const [badge, setBadge] = useState(() => getBadgeColor()); - - const updateTime = () => { - setInterval(() => { - setTime(() => getTime()); - setBadge(() => getBadgeColor()); - }, 30000); - }; - - useEffectOnce(updateTime); - - return {time}; - }; - - const columns = [ - { - field: 'name', - name: i18n.translate('pitManagement.pitTable.nameColumnName', { - defaultMessage: 'Name', - }), - }, - { - field: 'expiry', - name: i18n.translate('pitManagement.pitTable.expiresColumnName', { - defaultMessage: 'Expires', - }), - render: (t: number) => { - // return prettyDuration(moment(t).format('YYYY-MM-DDTHH:mm:ss'),'now',[], 'MMMM Do YYYY, HH:mm:ss.SSS') - return ; - }, - sortable: true, - }, - { - field: 'dataSource', - name: i18n.translate('pitManagement.pitTable.dataSourceColumnName', { - defaultMessage: 'Data Source', - }), - render: (t: string) => { - // return prettyDuration(moment(t).format('YYYY-MM-DDTHH:mm:ss'),'now',[], 'MMMM Do YYYY, HH:mm:ss.SSS') - return t === '' ? 'default' : t; - }, - }, - { - field: 'creation_time', - name: i18n.translate('pitManagement.pitTable.createdColumnName', { - defaultMessage: 'Created', - }), - render: (t: number) => { - const date = moment(t); - const formattedDate = date.format('MMM D, YYYY HH:mm:ss'); - return formattedDate; - }, - sortable: true, - }, - { - name: i18n.translate('pitManagement.pitTable.actionsColumnName', { - defaultMessage: 'Actions', - }), - actions, - }, - ]; - - const handleDeletePit = () => { - let dataSourceId: string | undefined = ''; - if (dataSource === '') { - dataSourceId = undefined; - } else { - const dataSourceObj = dataSources.filter((x) => x.title === dataSource); - if (dataSourceObj.length === 0) { - toasts.addDanger( - i18n.translate('pitManagement.pitTable.fetchDataSourceError', { - defaultMessage: 'Unable to find data source', - }) - ); - setMessage(); - setPits([]); - return; - } else { - dataSourceId = dataSourceObj[0].id; - } - } - - services - .deletePits( - selectedPits.map((x) => x.pit_id), - dataSourceId - ) - .then((deletedPits) => { - console.log(deletedPits); - getPits(dataSource); - }); - }; - - const renderToolsRight = () => { - return [ - - - , - ]; - }; - - const renderToolsLeft = () => { - return [ - ({ - value: source.title, - text: source.name, - }))} - value={dataSource} - onChange={(e) => setDataSource(e.target.value)} - />, - ]; - }; - - // function onQueryChange({ query }: { query: Query }) { - // if (query.ast.getFieldClauses('dataSource')) { - // const selectedDataSource = query.ast.getFieldClauses('dataSource')[0].value as string; - // setDataSource(selectedDataSource); - // } else { - // setMessage(); - // setDataSource('noDataSource'); - // } - // } - - const search: EuiSearchBarProps = { - toolsLeft: renderToolsLeft(), - toolsRight: renderToolsRight(), - // defaultQuery: 'dataSource:""', - // onChange: onQueryChange, - box: { - incremental: true, - schema: true, - disabled: pits.length === 0, - }, - // filters: [ - // { - // type: 'field_value_selection', - // searchThreshold: 5, - // field: 'dataSource', - // name: i18n.translate('pitManagement.pitTable.dataSourceFilterName', { - // defaultMessage: 'Data Source', - // }), - // multiSelect: false, - // options: dataSources.map((source) => ({ - // value: source.title, - // name: source.name, - // view: `${source.title}`, - // })), - // }, - // ], - }; - - const onSelectionChange = (selected: PitItem[]) => { - setSelectedPits(selected); - }; - - const selection = { - onSelectionChange, - }; - - const pagination = { - initialPageSize: 10, - pageSizeOptions: [5, 10, 25, 50], - }; - - const PageHeader = () => { - const [refreshTime, setRefreshTime] = useState(moment.now()); - const [timeSinceRefresh, setTimeSinceRefresh] = useState( - moment(refreshTime).fromNow(true) - ); - - const handleClick = () => { - getPits(dataSource); - setRefreshTime(moment.now()); - }; - - const updateTimeSinceRefresh = () => { - setInterval(() => { - setTimeSinceRefresh(moment(refreshTime).fromNow(true)); - }, 30000); - }; - - useEffectOnce(updateTimeSinceRefresh); - - return ( - <> - - - -

- -

-
-
- - - Last updated {timeSinceRefresh} ago - - - - - - - - {createButton} - - -
- -

- -

-
- - ); - }; - - return ( - <> - - - - - - - - - {/* Create PIT - Get PITs */} - - ); -}; - -export const PITTableWithRouter = withRouter(PITTable); \ No newline at end of file +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import React, { useEffect, useState } from 'react'; +import { RouteComponentProps, withRouter } from 'react-router-dom'; +import { useEffectOnce, useMount } from 'react-use'; +import { + EuiButton, + EuiInMemoryTable, + EuiPageContent, + EuiPageContentBody, + EuiSpacer, + EuiSearchBarProps, + Query, + EuiPageContentHeader, + EuiPageContentHeaderSection, + EuiTitle, + EuiText, + EuiFlexGroup, + EuiFlexItem, + EuiBadge, + EuiSelect, + EuiConfirmModal, + EuiFormRow, + EuiFieldText, +} from '@elastic/eui'; +import { i18n } from '@osd/i18n'; +import { FormattedMessage } from '@osd/i18n/react'; +import moment, { now } from 'moment'; +import { SavedObjectReference } from 'src/core/public'; +import { getListBreadcrumbs } from '../breadcrumbs'; +import { PointInTimeManagementContext } from '../../types'; +import { useOpenSearchDashboards } from '../../../../opensearch_dashboards_react/public'; +import { + getDataSources, + PointInTime, + createSavedObject, + getSavedPits, + deletePointInTimeById, + updatePointInTimeSavedObject, +} from '../utils'; +import { EmptyState, NoDataSourceState } from './empty_state'; +// import { PageHeader } from './page_header'; +import { getServices, Services } from '../../services'; +import { PointInTimeCreateForm } from '../create_pit'; +import { CreateButton } from '../create_button'; +// import { dataSource } from 'src/plugins/data_source/server/saved_objects'; + +export interface DataSourceItem { + id: string; + name: string; + title: string; + sort: string; +} + +export interface DashboardPitItem { + id: string; + name: string; + creation_time: number; + keep_alive: number; + delete_on_expiry: boolean; +} + +export interface PitItem { + pit_id: string; + name: string; + creation_time: number; + keep_alive: number; + dataSource: string; + expiry: number; +} + +const PITTable = ({ history }: RouteComponentProps) => { + const { + setBreadcrumbs, + savedObjects, + notifications: { toasts }, + http, + } = useOpenSearchDashboards().services; + + useMount(() => { + setBreadcrumbs(getListBreadcrumbs()); + }); + + const createButton = ; + + + const services: Services = getServices(http); + + // TODO: update this for cases when some data source name is default + const defaultDataSource: DataSourceItem = { id: '', title: '', sort: '0', name: 'default' }; + + // TODO: use APIs to fetch PITs and update the table and message + const [loading, setLoading] = useState(false); + const [pits, setPits] = useState([]); + const [pitsToDelete, setPitsToDelete] = useState([]); + const [selectedPits, setSelectedPits] = useState([]); + // const [dashboardPits, setDashboardPits] = useState([]); + const [message, setMessage] = useState(); + + const [dataSources, setDataSources] = useState([defaultDataSource]); + const [dataSource, setDataSource] = useState(''); + const [isModalVisible, setIsModalVisible] = useState(false); + + useEffectOnce(() => { + fetchDataSources(); + }); + + useEffect(() => { + getPits(dataSource); + }, [dataSource]); + + const fetchDataSources = () => { + getDataSources(savedObjects.client) + .then((fetchedDataSources) => { + if (fetchedDataSources?.length) { + setDataSources( + fetchedDataSources + .concat([defaultDataSource]) + .sort((a, b) => a.sort.localeCompare(b.sort)) + ); + } + }) + .catch(() => { + toasts.addDanger( + i18n.translate('pitManagement.pitTable.fetchDataSourceError', { + defaultMessage: 'Unable to find existing data sources', + }) + ); + }); + }; + + const navigateEdit = (pit) => { + console.log(pit); + history.push(`${pit.id}`); + }; + + const getPits = (dataSourceId?: string) => { + // setMessage(<>Loading PITs...); + setLoading(true); + console.log(dataSourceId); + // let dataSourceId: string | undefined; + const dataSourceName = dataSourceId; + if (dataSourceId === '') { + dataSourceId = undefined; + } else if (dataSourceId === 'noDataSource') { + // setMessage(); + setLoading(false); + setPits([]); + return; + } else { + const dataSource = dataSources.filter((x) => x.title === dataSourceId); + if (dataSource.length === 0) { + toasts.addDanger( + i18n.translate('pitManagement.pitTable.fetchDataSourceError', { + defaultMessage: 'Unable to find data source', + }) + ); + setMessage(); + setPits([]); + return; + } else { + dataSourceId = dataSource[0].id; + } + } + setMessage(); + console.log(dataSourceId); + + services + .getAllPits(dataSourceId) + .then((fetchedPits) => { + getSavedPits(savedObjects.client) + .then((fetchedDashboardPits) => { + // if (fetchedDataSources?.length) { + // setDashboardPits(fetchedDataSources); + // } + console.log('dashboard pits', fetchedDashboardPits); + setLoading(false); + if (fetchedPits?.resp?.pits) { + const expiredPits: DashboardPitItem[] = []; + // if (dataSourceId === undefined) { + // expiredPits = fetchedDashboardPits.filter( + // (x) => !fetchedPits?.resp?.pits.some((x2) => x.attributes.id === x2.pit_id) + // ); + // } + // console.log('expired', expiredPits); + // expiredPits.filter(x=>x.attributes.delete_on_expiry).forEach(x=> { + // console.log('deleting ', x) + // deletePointInTimeById(savedObjects.client, x.id); + // }) + + if (dataSourceId === undefined) { + fetchedDashboardPits.forEach((x) => { + if (!fetchedPits?.resp?.pits.some((x2) => x.attributes.pit_id === x2.pit_id)) { + if (x.attributes.delete_on_expiry) { + console.log('deleting ', x); + deletePointInTimeById(savedObjects.client, x.id); + } else { + expiredPits.push(x); + } + } + }); + } + console.log('expired', expiredPits); + + setPits( + fetchedPits?.resp?.pits + .map((val) => { + const date = moment(val.creation_time); + const formattedDate = date.format('MMM D @ HH:mm:ss'); + const expiry = val.creation_time + val.keep_alive; + const dashboardPit = fetchedDashboardPits.filter( + (x) => x.attributes.pit_id === val.pit_id + ); + if (dashboardPit.length > 0) { + console.log(dashboardPit); + dashboardPit[0].attributes.keepAlive = val.keep_alive; + console.log('updating', dashboardPit); + updatePointInTimeSavedObject( + savedObjects.client, + dashboardPit[0].id, + dashboardPit[0].attributes, + dashboardPit[0].references + ); + return { + pit_id: val.pit_id, + id: dashboardPit[0].id, + name: dashboardPit[0].attributes.name, + creation_time: val.creation_time, + keep_alive: val.keep_alive, + dataSource: dataSourceName, + isSavedObject: true, + expiry, + }; + } + return { + pit_id: val.pit_id, + id: val.id, + name: formattedDate, + creation_time: val.creation_time, + keep_alive: val.keep_alive, + dataSource: dataSourceName, + isSavedObject: false, + expiry, + }; + }) + .concat( + expiredPits.map((x) => ({ + pit_id: x.attributes.pit_id, + name: x.attributes.name, + id: x.id, + creation_time: x.attributes.creation_time, + keep_alive: x.attributes.keepAlive, + dataSource: dataSourceName, + isSavedObject: true, + expiry: x.attributes.creation_time + x.attributes.keepAlive, + })) + ) + ); + } + + console.log(fetchedPits?.resp?.pits as PitItem[]); + console.log(pits.length); + }) + .catch(() => { + toasts.addDanger( + i18n.translate('pitManagement.pitTable.fetchPitError', { + defaultMessage: 'Unable to load existing dashboard PITs', + }) + ); + }); + }) + .catch(() => { + setLoading(false); + toasts.addDanger( + i18n.translate('pitManagement.pitTable.fetchDataSourceError', { + defaultMessage: 'Unable to fetch point in time objects.', + }) + ); + }); + }; + + const createPointInTime = () => { + // setIsFlyoutVisible(false); + const pit: PointInTime = { + pit_id: + 'o463QQEKbXktaW5kZXgtMRZqUlZFU2lSaFE1eUx0cHdiSjNLWjRRABZtWjNCdk1ZdFRZbS1JbnltaVlBTWdBAAAAAAAAAACGFlJXLVVNYXVQVFctQVIxVmh1OUJuSlEBFmpSVkVTaVJoUTV5THRwd2JKM0taNFEAAA==', + keepAlive: 30000000, + creation_time: 1684418768188, + name: 'PIT-my-index-1223', // Todo create pit and fill the pit id + delete_on_expiry: false, + }; + + const reference: SavedObjectReference = { + id: '5586e600-f57b-11ed-90e3-a75eeb2a18a5', + type: 'index-pattern', + name: 'my*', + }; + createSavedObject(pit, savedObjects.client, reference); + }; + + const getBackendPits = () => { + getSavedPits(savedObjects.client).then((fetchedDashboardPits) => { + console.log(fetchedDashboardPits); + }); + }; + + const deletePit = (pit) => { + let dataSourceId: string | undefined = ''; + if (dataSource === '') { + dataSourceId = undefined; + } else { + const dataSourceObj = dataSources.filter((x) => x.title === dataSource); + if (dataSourceObj.length === 0) { + toasts.addDanger( + i18n.translate('pitManagement.pitTable.fetchDataSourceError', { + defaultMessage: 'Unable to find data source', + }) + ); + setMessage(); + setPits([]); + return; + } else { + dataSourceId = dataSourceObj[0].id; + } + } + services.deletePits([pit.pit_id], dataSourceId).then((deletedPits) => { + console.log(deletedPits); + getPits(dataSource); + }); + }; + + const DeleteModal = ({}) => { + const closeModal = () => { + setIsModalVisible(false); + }; + + const [value, setValue] = useState(''); + const onChange = (e) => { + setValue(e.target.value); + console.log(pitsToDelete[0]); + }; + + let modal; + + if (isModalVisible) { + const expired = moment(pitsToDelete[0].expiry).isBefore(now()); + if (expired) { + modal = ( + { + closeModal(); + deletePit(pitsToDelete[0]); + setPitsToDelete([]); + }} + confirmButtonText="Delete PIT" + cancelButtonText="Cancel" + buttonColor="danger" + > + The PIT will be permanently deleted. This action is irreversible. + + + ); + } else { + modal = ( + { + closeModal(); + deletePit(pitsToDelete[0]); + setPitsToDelete([]); + }} + confirmButtonText="Delete PIT" + cancelButtonText="Cancel" + buttonColor="danger" + confirmButtonDisabled={value !== pitsToDelete[0].name} + > + + This is an active PIT. Deleting it will permanently remove data and may cause + unexpected behavior in saved objects that use this PIT. This action is irreversible. + + + + + + + ); + } + } + + return
{modal}
; + }; + + const displayDelete = (pit) => { + setPitsToDelete([pit]); + setIsModalVisible(true); + }; + + const actions = [ + { + name: 'Add Time', + description: 'Add Time', + icon: 'clock', + type: 'icon', + onClick: fetchDataSources, + }, + { + name: 'Configure PIT', + description: 'Configure PIT', + icon: 'pencil', + type: 'icon', + onClick: navigateEdit, // route it to edit page --> create a route page + }, + { + name: 'Delete', + description: 'Delete PIT', + icon: 'trash', + type: 'icon', + color: 'danger', + onClick: displayDelete, + }, + ]; + + const Timer = ({ endTime }) => { + const getTime = () => + moment(endTime).isBefore(now()) ? 'Expired' : '~ ' + moment(endTime).fromNow(true); + + const getBadgeColor = () => { + const timeLeft = endTime - moment.now().valueOf(); + if (timeLeft < 0) { + return 'hollow'; + } else if (timeLeft < 10 * 60 * 1000) { + return 'danger'; + } else { + return 'default'; + } + }; + + const [time, setTime] = useState(() => getTime()); + const [badge, setBadge] = useState(() => getBadgeColor()); + + const updateTime = () => { + setInterval(() => { + setTime(() => getTime()); + setBadge(() => getBadgeColor()); + }, 30000); + }; + + useEffectOnce(updateTime); + + return {time}; + }; + + const columns = [ + { + field: 'name', + name: i18n.translate('pitManagement.pitTable.nameColumnName', { + defaultMessage: 'Name', + }), + }, + { + field: 'expiry', + name: i18n.translate('pitManagement.pitTable.expiresColumnName', { + defaultMessage: 'Expires', + }), + render: (t: number) => { + // return prettyDuration(moment(t).format('YYYY-MM-DDTHH:mm:ss'),'now',[], 'MMMM Do YYYY, HH:mm:ss.SSS') + return ; + }, + sortable: true, + }, + { + field: 'dataSource', + name: i18n.translate('pitManagement.pitTable.dataSourceColumnName', { + defaultMessage: 'Data Source', + }), + render: (t: string) => { + // return prettyDuration(moment(t).format('YYYY-MM-DDTHH:mm:ss'),'now',[], 'MMMM Do YYYY, HH:mm:ss.SSS') + return t === '' ? 'default' : t; + }, + }, + { + field: 'creation_time', + name: i18n.translate('pitManagement.pitTable.createdColumnName', { + defaultMessage: 'Created', + }), + render: (t: number) => { + const date = moment(t); + const formattedDate = date.format('MMM D, YYYY HH:mm:ss'); + return formattedDate; + }, + sortable: true, + }, + { + name: i18n.translate('pitManagement.pitTable.actionsColumnName', { + defaultMessage: 'Actions', + }), + actions, + }, + ]; + + const handleDeletePit = () => { + let dataSourceId: string | undefined = ''; + if (dataSource === '') { + dataSourceId = undefined; + } else { + const dataSourceObj = dataSources.filter((x) => x.title === dataSource); + if (dataSourceObj.length === 0) { + toasts.addDanger( + i18n.translate('pitManagement.pitTable.fetchDataSourceError', { + defaultMessage: 'Unable to find data source', + }) + ); + setMessage(); + setPits([]); + return; + } else { + dataSourceId = dataSourceObj[0].id; + } + } + + services + .deletePits( + selectedPits.map((x) => x.pit_id), + dataSourceId + ) + .then((deletedPits) => { + console.log(deletedPits); + getPits(dataSource); + }); + }; + + const renderToolsRight = () => { + return [ + + + , + ]; + }; + + const renderToolsLeft = () => { + return [ + ({ + value: source.title, + text: source.name, + }))} + value={dataSource} + onChange={(e) => setDataSource(e.target.value)} + />, + ]; + }; + + // function onQueryChange({ query }: { query: Query }) { + // if (query.ast.getFieldClauses('dataSource')) { + // const selectedDataSource = query.ast.getFieldClauses('dataSource')[0].value as string; + // setDataSource(selectedDataSource); + // } else { + // setMessage(); + // setDataSource('noDataSource'); + // } + // } + + const search: EuiSearchBarProps = { + toolsLeft: renderToolsLeft(), + toolsRight: renderToolsRight(), + // defaultQuery: 'dataSource:""', + // onChange: onQueryChange, + box: { + incremental: true, + schema: true, + disabled: pits.length === 0, + }, + // filters: [ + // { + // type: 'field_value_selection', + // searchThreshold: 5, + // field: 'dataSource', + // name: i18n.translate('pitManagement.pitTable.dataSourceFilterName', { + // defaultMessage: 'Data Source', + // }), + // multiSelect: false, + // options: dataSources.map((source) => ({ + // value: source.title, + // name: source.name, + // view: `${source.title}`, + // })), + // }, + // ], + }; + + const onSelectionChange = (selected: PitItem[]) => { + setSelectedPits(selected); + }; + + const selection = { + onSelectionChange, + }; + + const pagination = { + initialPageSize: 10, + pageSizeOptions: [5, 10, 25, 50], + }; + + const PageHeader = () => { + const [refreshTime, setRefreshTime] = useState(moment.now()); + const [timeSinceRefresh, setTimeSinceRefresh] = useState( + moment(refreshTime).fromNow(true) + ); + + const handleClick = () => { + getPits(dataSource); + setRefreshTime(moment.now()); + }; + + const updateTimeSinceRefresh = () => { + setInterval(() => { + setTimeSinceRefresh(moment(refreshTime).fromNow(true)); + }, 30000); + }; + + useEffectOnce(updateTimeSinceRefresh); + + return ( + <> + + + +

+ +

+
+
+ + + Last updated {timeSinceRefresh} ago + + + + + + + + {createButton} + + +
+ +

+ +

+
+ + ); + }; + + return ( + <> + + + + + + + + + {/* Create PIT + Get PITs */} + + ); +}; + +export const PITTableWithRouter = withRouter(PITTable); diff --git a/src/plugins/point_in_time_management/public/components/utils.ts b/src/plugins/point_in_time_management/public/components/utils.ts index fc1522624901..12463fa4735b 100644 --- a/src/plugins/point_in_time_management/public/components/utils.ts +++ b/src/plugins/point_in_time_management/public/components/utils.ts @@ -1,259 +1,259 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ - - - -import { HttpStart, SavedObjectReference, SavedObjectsClientContract } from 'src/core/public'; -import { DataSourceAttributes } from 'src/plugins/data_source/common/data_sources'; -import { PointInTimeAttributes } from '../types'; -import { ResolveIndexResponse } from 'src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/types'; - -export async function getDataSources(savedObjectsClient: SavedObjectsClientContract) { - return savedObjectsClient - .find({ - type: 'data-source', - fields: ['title', 'id'], - perPage: 10000, - }) - .then((response) => { - return ( - response.savedObjects.map((dataSource) => { - const id = dataSource.id; - const title = dataSource.get('title'); - - return { - id, - title, - name: title, - sort: `${title}`, - }; - }) || [] - ); - }); -} - -// export async function getDashboardPits(savedObjectsClient: SavedObjectsClientContract) { -// return savedObjectsClient -// .find({ -// type: 'data-source', -// fields: ['title', 'id'], -// perPage: 10000, -// }) -// .then((response) => { -// return [ -// { -// name: 'PIT-my-index-1', -// id: -// 'o463QQEKbXktaW5kZXgtMRZtN2RWMHdaRlNILThIMUVWWDJJMVBRABZxMlNNZVdPZVRGbVR6MUxPc1RZYkx3AAAAAAAAAAAiFmhZdDNoTk9hUlBlVng2RVNIMUNhelEBFm03ZFYwd1pGU0gtOEgxRVZYMkkxUFEAAA==', -// creation_time: 1681386155468, -// keep_alive: 600000, -// }, -// { -// name: 'PIT-my-index-2', -// id: -// 'o463QQEKbXktaW5kZXgtMRZtN2RWMHdaRlNILThIMUVWWDJJMVBRABZxMlNNZVdPZVRGbVR6MUxPc1RZYkx3AAAAAAAAAAAjFmhZdDNoTk9hUlBlVng2RVNIMUNhelEBFm03ZFYwd1pGU0gtOEgxRVZYMkkxUFEAAA==', -// creation_time: 1681386155468, -// keep_alive: 600000, -// }, -// ]; -// }); -// } - -export interface PointInTime { - name: string; - keepAlive: number; - pit_id: string; - creation_time: number; - id?: string; - delete_on_expiry: boolean; -} -// export interface SavedObjectReference { -// name?: string; -// id: string; -// type: string; -// } - -export async function getIndexPatterns(savedObjectsClient: SavedObjectsClientContract) { - return ( - savedObjectsClient - .find({ - type: 'index-pattern', - fields: ['title', 'type'], - perPage: 10000, - }) - .then((response) => - response.savedObjects - .map((pattern) => { - const id = pattern.id; - const title = pattern.get('title'); - - return { - id, - title, - // the prepending of 0 at the default pattern takes care of prioritization - // so the sorting will but the default index on top - // or on bottom of a the table - sort: `${title}`, - }; - }) - .sort((a, b) => { - if (a.sort < b.sort) { - return -1; - } else if (a.sort > b.sort) { - return 1; - } else { - return 0; - } - }) - ) || [] - ); -} - -export async function getSavedPits(client: SavedObjectsClientContract) { - const savedObjects = await client.find({ - type: 'point-in-time', - perPage: 1000, - fields: ['id', 'creation_time', 'keepAlive', 'name', 'pit_id', 'delete_on_expiry'], - }); - - return savedObjects.savedObjects; -} - -export async function findById(client: SavedObjectsClientContract, id: string) { - if (id) { - console.log(id); - const savedObjects = await client.find({ - type: 'point-in-time', - perPage: 1000, - fields: [], - }); - return savedObjects.savedObjects.find((obj) => obj.id === id); - } -} - -export async function updatePointInTimeById( - savedObjectsClient: SavedObjectsClientContract, - id: string, - attributes: PointInTimeAttributes -) { - return savedObjectsClient.update('point-in-time', id, attributes); -} - -export async function updatePointInTimeSavedObject( - savedObjectsClient: SavedObjectsClientContract, - id: string, - attributes: PointInTimeAttributes, - reference: SavedObjectReference[] -) { - return savedObjectsClient.update('point-in-time', id, attributes, { references: reference }); -} - -export async function deletePointInTimeById( - savedObjectsClient: SavedObjectsClientContract, - id: string -) { - return savedObjectsClient.delete('point-in-time', id); -} - -export async function updatePointInTimeKeepAlive( - savedObjectsClient: SavedObjectsClientContract, - id: string, - addTime: number -) {} - -export async function createSavedObject( - pointintime: PointInTime, - client: SavedObjectsClientContract, - reference: SavedObjectReference -) { - const dupe = await findById(client, pointintime.pit_id); - console.log('This is dupe output'); - console.log(dupe); - if (dupe) { - throw new Error(`Duplicate Point in time: ${pointintime.pit_id}`); - } - // if (dupe) { - // if (override) { - // await this.delete(dupe.id); - // } else { - // throw new DuplicateIndexPatternError(`Duplicate index pattern: ${indexPattern.title}`); - // } - // } - - const body = pointintime; - const references = [{ ...reference }]; - const savedObjectType = 'point-in-time'; - const response = await client.create(savedObjectType, body, { - references, - }); - console.log('This is the response'); - console.log(response); - pointintime.id = response.id; - console.log(pointintime); - return pointintime; -} -export async function getIndicesViaResolve ( - http: HttpStart, - //getIndexTags: IndexPatternCreationConfig['getIndexTags'], - pattern: string, - showAllIndices: boolean, - dataSourceId?: string -) { - const query = {} as any; - if (showAllIndices) { - query.expand_wildcards = 'all'; - } - if (dataSourceId) { - query.data_source = dataSourceId; - } - - return http - .get(`/internal/index-pattern-management/resolve_index/${pattern}`, { - query, - }) - .then((response) => { - if (!response) { - return []; - } else { - const source: any[] | PromiseLike = []; - - (response.indices || []).forEach((index) => { - - source.push({ - name: index.name, - item: index, - }); - }); - return source; - } - }); - }; - - export async function getFieldsForWildcard(indexPattern: string, capabilities: any, indexPatternsService: any) { - - return await indexPatternsService!.getFieldsForWildcard({ - pattern: indexPattern, - fieldCapsOptions: { allowNoIndices: true }, - }); -} - -export async function createIndexPattern(indexPatternId: string, indexPatternsService: any, dataSourceRef:any) { - //let emptyPattern: IndexPattern;indexPatternsService - try { - return await indexPatternsService.createAndSave({ - title: indexPatternId, - id: "", - dataSourceRef, - }); - } catch (err) { - // if (err instanceof DuplicateIndexPatternError) { - - - // return; - // } else { - // throw err; - // } - } -}; \ No newline at end of file +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + + + +import { HttpStart, SavedObjectReference, SavedObjectsClientContract } from 'src/core/public'; +import { DataSourceAttributes } from 'src/plugins/data_source/common/data_sources'; +import { PointInTimeAttributes } from '../types'; +import { ResolveIndexResponse } from 'src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/types'; + +export async function getDataSources(savedObjectsClient: SavedObjectsClientContract) { + return savedObjectsClient + .find({ + type: 'data-source', + fields: ['title', 'id'], + perPage: 10000, + }) + .then((response) => { + return ( + response.savedObjects.map((dataSource) => { + const id = dataSource.id; + const title = dataSource.get('title'); + + return { + id, + title, + name: title, + sort: `${title}`, + }; + }) || [] + ); + }); +} + +// export async function getDashboardPits(savedObjectsClient: SavedObjectsClientContract) { +// return savedObjectsClient +// .find({ +// type: 'data-source', +// fields: ['title', 'id'], +// perPage: 10000, +// }) +// .then((response) => { +// return [ +// { +// name: 'PIT-my-index-1', +// id: +// 'o463QQEKbXktaW5kZXgtMRZtN2RWMHdaRlNILThIMUVWWDJJMVBRABZxMlNNZVdPZVRGbVR6MUxPc1RZYkx3AAAAAAAAAAAiFmhZdDNoTk9hUlBlVng2RVNIMUNhelEBFm03ZFYwd1pGU0gtOEgxRVZYMkkxUFEAAA==', +// creation_time: 1681386155468, +// keep_alive: 600000, +// }, +// { +// name: 'PIT-my-index-2', +// id: +// 'o463QQEKbXktaW5kZXgtMRZtN2RWMHdaRlNILThIMUVWWDJJMVBRABZxMlNNZVdPZVRGbVR6MUxPc1RZYkx3AAAAAAAAAAAjFmhZdDNoTk9hUlBlVng2RVNIMUNhelEBFm03ZFYwd1pGU0gtOEgxRVZYMkkxUFEAAA==', +// creation_time: 1681386155468, +// keep_alive: 600000, +// }, +// ]; +// }); +// } + +export interface PointInTime { + name: string; + keepAlive: number; + pit_id: string; + creation_time: number; + id?: string; + delete_on_expiry: boolean; +} +// export interface SavedObjectReference { +// name?: string; +// id: string; +// type: string; +// } + +export async function getIndexPatterns(savedObjectsClient: SavedObjectsClientContract) { + return ( + savedObjectsClient + .find({ + type: 'index-pattern', + fields: ['title', 'type'], + perPage: 10000, + }) + .then((response) => + response.savedObjects + .map((pattern) => { + const id = pattern.id; + const title = pattern.get('title'); + + return { + id, + title, + // the prepending of 0 at the default pattern takes care of prioritization + // so the sorting will but the default index on top + // or on bottom of a the table + sort: `${title}`, + }; + }) + .sort((a, b) => { + if (a.sort < b.sort) { + return -1; + } else if (a.sort > b.sort) { + return 1; + } else { + return 0; + } + }) + ) || [] + ); +} + +export async function getSavedPits(client: SavedObjectsClientContract) { + const savedObjects = await client.find({ + type: 'point-in-time', + perPage: 1000, + fields: ['id', 'creation_time', 'keepAlive', 'name', 'pit_id', 'delete_on_expiry'], + }); + + return savedObjects.savedObjects; +} + +export async function findById(client: SavedObjectsClientContract, id: string) { + if (id) { + console.log(id); + const savedObjects = await client.find({ + type: 'point-in-time', + perPage: 1000, + fields: [], + }); + return savedObjects.savedObjects.find((obj) => obj.id === id); + } +} + +export async function updatePointInTimeById( + savedObjectsClient: SavedObjectsClientContract, + id: string, + attributes: PointInTimeAttributes +) { + return savedObjectsClient.update('point-in-time', id, attributes); +} + +export async function updatePointInTimeSavedObject( + savedObjectsClient: SavedObjectsClientContract, + id: string, + attributes: PointInTimeAttributes, + reference: SavedObjectReference[] +) { + return savedObjectsClient.update('point-in-time', id, attributes, { references: reference }); +} + +export async function deletePointInTimeById( + savedObjectsClient: SavedObjectsClientContract, + id: string +) { + return savedObjectsClient.delete('point-in-time', id); +} + +export async function updatePointInTimeKeepAlive( + savedObjectsClient: SavedObjectsClientContract, + id: string, + addTime: number +) {} + +export async function createSavedObject( + pointintime: PointInTime, + client: SavedObjectsClientContract, + reference: SavedObjectReference +) { + const dupe = await findById(client, pointintime.pit_id); + console.log('This is dupe output'); + console.log(dupe); + if (dupe) { + throw new Error(`Duplicate Point in time: ${pointintime.pit_id}`); + } + // if (dupe) { + // if (override) { + // await this.delete(dupe.id); + // } else { + // throw new DuplicateIndexPatternError(`Duplicate index pattern: ${indexPattern.title}`); + // } + // } + + const body = pointintime; + const references = [{ ...reference }]; + const savedObjectType = 'point-in-time'; + const response = await client.create(savedObjectType, body, { + references, + }); + console.log('This is the response'); + console.log(response); + pointintime.id = response.id; + console.log(pointintime); + return pointintime; +} +export async function getIndicesViaResolve ( + http: HttpStart, + //getIndexTags: IndexPatternCreationConfig['getIndexTags'], + pattern: string, + showAllIndices: boolean, + dataSourceId?: string +) { + const query = {} as any; + if (showAllIndices) { + query.expand_wildcards = 'all'; + } + if (dataSourceId) { + query.data_source = dataSourceId; + } + + return http + .get(`/internal/index-pattern-management/resolve_index/${pattern}`, { + query, + }) + .then((response) => { + if (!response) { + return []; + } else { + const source: any[] | PromiseLike = []; + + (response.indices || []).forEach((index) => { + + source.push({ + name: index.name, + item: index, + }); + }); + return source; + } + }); + }; + + export async function getFieldsForWildcard(indexPattern: string, capabilities: any, indexPatternsService: any) { + + return await indexPatternsService!.getFieldsForWildcard({ + pattern: indexPattern, + fieldCapsOptions: { allowNoIndices: true }, + }); +} + +export async function createIndexPattern(indexPatternId: string, indexPatternsService: any, dataSourceRef:any) { + //let emptyPattern: IndexPattern;indexPatternsService + try { + return await indexPatternsService.createAndSave({ + title: indexPatternId, + id: "", + dataSourceRef, + }); + } catch (err) { + // if (err instanceof DuplicateIndexPatternError) { + + + // return; + // } else { + // throw err; + // } + } +}; diff --git a/src/plugins/point_in_time_management/public/management_app/mount_management_section.tsx b/src/plugins/point_in_time_management/public/management_app/mount_management_section.tsx index 30548d86aee4..1a0478091054 100644 --- a/src/plugins/point_in_time_management/public/management_app/mount_management_section.tsx +++ b/src/plugins/point_in_time_management/public/management_app/mount_management_section.tsx @@ -1,62 +1,62 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; -import ReactDOM from 'react-dom'; -import { I18nProvider } from '@osd/i18n/react'; -import { Route, Router, Switch } from 'react-router-dom'; -import { ManagementAppMountParams } from '../../../management/public'; -import { PointInTimeManagementStartDependencies } from '../plugin'; -import { StartServicesAccessor } from '../../../../core/public'; -import { PointInTimeManagementContext } from '../types'; -import { OpenSearchDashboardsContextProvider } from '../../../opensearch_dashboards_react/public'; -import { PITTableWithRouter } from '../components'; -import { PITEditWithRouter } from '../components/pit_edit'; -import { CreatePitWithRouter } from '../components/create_pit/create_pit'; - -export async function mountManagementSection( - getStartServices: StartServicesAccessor, - params: ManagementAppMountParams -) { - const [{ chrome, application, savedObjects, notifications, http }, {data}] = await getStartServices(); - const deps: PointInTimeManagementContext = { - chrome, - application, - notifications, - savedObjects, - http, - data, - setBreadcrumbs: params.setBreadcrumbs, - }; - ReactDOM.render( - - - - - - - - - - - - {/* - - */} - - - - - - - , - params.element - ); - - return () => { - chrome.docTitle.reset(); - ReactDOM.unmountComponentAtNode(params.element); - }; -} +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import React from 'react'; +import ReactDOM from 'react-dom'; +import { I18nProvider } from '@osd/i18n/react'; +import { Route, Router, Switch } from 'react-router-dom'; +import { ManagementAppMountParams } from '../../../management/public'; +import { PointInTimeManagementStartDependencies } from '../plugin'; +import { StartServicesAccessor } from '../../../../core/public'; +import { PointInTimeManagementContext } from '../types'; +import { OpenSearchDashboardsContextProvider } from '../../../opensearch_dashboards_react/public'; +import { PITTableWithRouter } from '../components'; +import { PITEditWithRouter } from '../components/pit_edit'; +import { CreatePitWithRouter } from '../components/create_pit/create_pit'; + +export async function mountManagementSection( + getStartServices: StartServicesAccessor, + params: ManagementAppMountParams +) { + const [{ chrome, application, savedObjects, notifications, http }, {data}] = await getStartServices(); + const deps: PointInTimeManagementContext = { + chrome, + application, + notifications, + savedObjects, + http, + data, + setBreadcrumbs: params.setBreadcrumbs, + }; + ReactDOM.render( + + + + + + + + + + + + {/* + + */} + + + + + + + , + params.element + ); + + return () => { + chrome.docTitle.reset(); + ReactDOM.unmountComponentAtNode(params.element); + }; +} diff --git a/src/plugins/point_in_time_management/public/services.ts b/src/plugins/point_in_time_management/public/services.ts index bb7842b06f99..d956efa22995 100644 --- a/src/plugins/point_in_time_management/public/services.ts +++ b/src/plugins/point_in_time_management/public/services.ts @@ -1,82 +1,82 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { CoreStart, HttpFetchError } from 'opensearch-dashboards/public'; - -export interface Services { - getAllPits: (dataSourceId?: string) => Promise; - deletePits: (pits: string[], dataSourceId?: string) => any; - createPit: (index: string, keepAlive: string, allowPartialCreation: boolean, dataSourceId?: string) => any; - addPitTime: (pit_id: string, keepAlive: string, dataSourceId?: string) => any; -} - -export function getServices(http: CoreStart['http']): Services { - return { - getAllPits: async (dataSourceId?: string) => { - try { - const response = await http.post('/api/pit/all', { - body: JSON.stringify({ - dataSourceId: dataSourceId ? dataSourceId : '', - }), - }); - console.log('These are backend PITs'); - console.log(response); - return response; - } catch (e) { - return e; - } - }, - addPitTime: async (pit_id: string, keepAlive: string, dataSourceId?: string) => { - try { - console.log(pit_id, keepAlive, dataSourceId); - const response = await http.post('/api/pit/addTime', { - body: JSON.stringify({ - dataSourceId: dataSourceId ? dataSourceId : 'default', - pit_id, - keepAlive, - }), - }); - console.log('Updated the PIT KeepAlive'); - console.log(response); - } catch (e) { - return e; - } - }, - - deletePits: async (pits: string[], dataSourceId?: string) => { - try { - const response = await http.post('/api/pit/delete', { - body: JSON.stringify({ - dataSourceId: dataSourceId ? dataSourceId : '', - pit_id: pits, - }), - }); - return response; - } catch (e) { - return e; - } - }, - - createPit: async (index: string, keepAlive: string, allowPartialCreation: boolean, dataSourceId?: string) => { - try { - console.log("create pit : " + dataSourceId) - const response = await http.post('/api/pit/create/'+index, { - body: JSON.stringify({ - dataSourceId: dataSourceId ? dataSourceId : '', - }), - query: { - keepAlive: keepAlive, - allowPartialFailures : allowPartialCreation - } - }); - console.log("create pit response") - console.log(response) - return response; - } catch (e) { - return e; - } - }, - }; -} +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { CoreStart, HttpFetchError } from 'opensearch-dashboards/public'; + +export interface Services { + getAllPits: (dataSourceId?: string) => Promise; + deletePits: (pits: string[], dataSourceId?: string) => any; + createPit: (index: string, keepAlive: string, allowPartialCreation: boolean, dataSourceId?: string) => any; + addPitTime: (pit_id: string, keepAlive: string, dataSourceId?: string) => any; +} + +export function getServices(http: CoreStart['http']): Services { + return { + getAllPits: async (dataSourceId?: string) => { + try { + const response = await http.post('/api/pit/all', { + body: JSON.stringify({ + dataSourceId: dataSourceId ? dataSourceId : '', + }), + }); + console.log('These are backend PITs'); + console.log(response); + return response; + } catch (e) { + return e; + } + }, + addPitTime: async (pit_id: string, keepAlive: string, dataSourceId?: string) => { + try { + console.log(pit_id, keepAlive, dataSourceId); + const response = await http.post('/api/pit/addTime', { + body: JSON.stringify({ + dataSourceId: dataSourceId ? dataSourceId : 'default', + pit_id, + keepAlive, + }), + }); + console.log('Updated the PIT KeepAlive'); + console.log(response); + } catch (e) { + return e; + } + }, + + deletePits: async (pits: string[], dataSourceId?: string) => { + try { + const response = await http.post('/api/pit/delete', { + body: JSON.stringify({ + dataSourceId: dataSourceId ? dataSourceId : '', + pit_id: pits, + }), + }); + return response; + } catch (e) { + return e; + } + }, + + createPit: async (index: string, keepAlive: string, allowPartialCreation: boolean, dataSourceId?: string) => { + try { + console.log("create pit : " + dataSourceId) + const response = await http.post('/api/pit/create/'+index, { + body: JSON.stringify({ + dataSourceId: dataSourceId ? dataSourceId : '', + }), + query: { + keepAlive: keepAlive, + allowPartialFailures : allowPartialCreation + } + }); + console.log("create pit response") + console.log(response) + return response; + } catch (e) { + return e; + } + }, + }; +} diff --git a/src/plugins/point_in_time_management/public/types.ts b/src/plugins/point_in_time_management/public/types.ts index b7c2e115c539..8a2238cafebc 100644 --- a/src/plugins/point_in_time_management/public/types.ts +++ b/src/plugins/point_in_time_management/public/types.ts @@ -3,13 +3,34 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { ApplicationStart, ChromeStart, HttpSetup } from 'opensearch-dashboards/public'; +import { + ApplicationStart, + ChromeStart, + HttpSetup, + SavedObjectAttributes, +} from 'opensearch-dashboards/public'; import { NotificationsStart, SavedObjectsStart } from 'src/core/public'; import { NavigationPublicPluginStart } from '../../navigation/public'; import { ManagementAppMountParams } from '../../management/public'; import { ManagementSetup } from '../../management/public'; import { DataPublicPluginStart } from 'src/plugins/data/public'; +export interface PointInTimeAttributes extends SavedObjectAttributes { + creation_time?: number; + keepAlive: number; + name: string; + pit_id?: string; + id?: string; + addtime: number; + delete_on_expiry: boolean; +} + +export interface ToastMessageItem { + id: string; + defaultMessage: string; + success?: boolean; +} + export interface PointInTimeManagementContext { chrome: ChromeStart; application: ApplicationStart; diff --git a/src/plugins/point_in_time_management/server/routes/opensearch.ts b/src/plugins/point_in_time_management/server/routes/opensearch.ts index be9b37de4cc0..d64754fce7f9 100644 --- a/src/plugins/point_in_time_management/server/routes/opensearch.ts +++ b/src/plugins/point_in_time_management/server/routes/opensearch.ts @@ -1,179 +1,178 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { schema } from '@osd/config-schema'; -import { - IRouter, - OpenSearchClient, - OpenSearchDashboardsRequest, - RequestHandlerContext, -} from 'opensearch-dashboards/server'; - -export function registerPitRoutes(router: IRouter) { - router.post( - { - path: '/api/pit/all', - validate: { - body: schema.object({ - dataSourceId: schema.string(), - }), - }, - }, - async (context, req, res) => { - const client: OpenSearchClient = await getClient(req, context); - try { - const pits = await client.getAllPits({}); - return res.ok({ - body: { - ok: true, - resp: pits.body, - }, - }); - } catch (err: any) { - return res.ok({ - body: { - ok: false, - resp: err.message, - }, - }); - } - } - ); - - router.post( - { - path: '/api/pit/addTime', - validate: { - body: schema.object({ - dataSourceId: schema.string(), - pit_id: schema.string(), - keepAlive: schema.string(), - }), - }, - }, - async (context, req, res) => { - const client: OpenSearchClient = await getClient(req, context); - console.log(req.body); - try { - const response = await client.search({ - body: { - size: 0, - pit: { - id: req.body.pit_id, - keep_alive: req.body.keepAlive, - }, - }, - }); - return res.ok({ - body: { - ok: true, - resp: response.body, - }, - }); - } catch (err: any) { - return res.ok({ - body: { - ok: false, - resp: err.message, - }, - }); - } - } - ); - router.post( - { - path: '/api/pit/delete', - validate: { - body: schema.object({ - dataSourceId: schema.string(), - pit_id: schema.arrayOf(schema.string()), - }), - }, - }, - async (context, req, res) => { - const client: OpenSearchClient = await getClient(req, context); - try { - const pits = await client.deletePit({ body: { pit_id: req.body.pit_id } }); - return res.ok({ - body: { - ok: true, - resp: pits.body, - }, - }); - } catch (err: any) { - return res.ok({ - body: { - ok: false, - resp: err.message, - }, - }); - } - } - ); - - router.post( - { - path: `/api/pit/create/{index}`, - validate: { - params: schema.object({ - index: schema.string(), - }), - query: schema.object( - { - allowPartialFailures: schema.boolean({ defaultValue: true }), - keepAlive: schema.string() - }, - ), - body: schema.object({ - dataSourceId: schema.string(), - }), - }, - }, - async (context, request, response) => { - console.log('This is the request for create point in time path'); - console.log(request); - const { index } = request.params; - const {keepAlive, allowPartialFailures} = request.query - console.log(index); - console.log(context); - // eslint-disable-next-line @typescript-eslint/naming-convention - debugger; - const client: OpenSearchClient = await getClient(request, context); - - const response_local = await client.createPit({ - index, - keep_alive: keepAlive, - allow_partial_pit_creation: allowPartialFailures - }, - {} - ); - console.log('This is after posting', response_local); - return response.ok({ - body: { - pit_id: response_local.body.pit_id, - creation_time: response_local.body.creation_time, - }, - }); - } - ); -} - -async function getClient( - req: OpenSearchDashboardsRequest< - unknown, - unknown, - Readonly<{} & { dataSourceId: string }>, - 'post' - >, - context: RequestHandlerContext -): Promise { - return req.body.dataSourceId && req.body.dataSourceId !== 'default' && context.dataSource - ? await context.dataSource.opensearch.getClient(req.body.dataSourceId) - : context.core.opensearch.client.asCurrentUser; -} -function trimEnd(arg0: string, arg1: string) { - throw new Error('Function not implemented.'); -} - +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { schema } from '@osd/config-schema'; +import { + IRouter, + OpenSearchClient, + OpenSearchDashboardsRequest, + RequestHandlerContext, +} from 'opensearch-dashboards/server'; + +export function registerPitRoutes(router: IRouter) { + router.post( + { + path: '/api/pit/all', + validate: { + body: schema.object({ + dataSourceId: schema.string(), + }), + }, + }, + async (context, req, res) => { + const client: OpenSearchClient = await getClient(req, context); + try { + const pits = await client.getAllPits({}); + return res.ok({ + body: { + ok: true, + resp: pits.body, + }, + }); + } catch (err: any) { + return res.ok({ + body: { + ok: false, + resp: err.message, + }, + }); + } + } + ); + + router.post( + { + path: '/api/pit/addTime', + validate: { + body: schema.object({ + dataSourceId: schema.string(), + pit_id: schema.string(), + keepAlive: schema.string(), + }), + }, + }, + async (context, req, res) => { + const client: OpenSearchClient = await getClient(req, context); + console.log(req.body); + try { + const response = await client.search({ + body: { + size: 0, + pit: { + id: req.body.pit_id, + keep_alive: req.body.keepAlive, + }, + }, + }); + return res.ok({ + body: { + ok: true, + resp: response.body, + }, + }); + } catch (err: any) { + return res.ok({ + body: { + ok: false, + resp: err.message, + }, + }); + } + } + ); + router.post( + { + path: '/api/pit/delete', + validate: { + body: schema.object({ + dataSourceId: schema.string(), + pit_id: schema.arrayOf(schema.string()), + }), + }, + }, + async (context, req, res) => { + const client: OpenSearchClient = await getClient(req, context); + try { + const pits = await client.deletePit({ body: { pit_id: req.body.pit_id } }); + return res.ok({ + body: { + ok: true, + resp: pits.body, + }, + }); + } catch (err: any) { + return res.ok({ + body: { + ok: false, + resp: err.message, + }, + }); + } + } + ); + + router.post( + { + path: `/api/pit/create/{index}`, + validate: { + params: schema.object({ + index: schema.string(), + }), + query: schema.object( + { + allowPartialFailures: schema.boolean({ defaultValue: true }), + keepAlive: schema.string() + }, + ), + body: schema.object({ + dataSourceId: schema.string(), + }), + }, + }, + async (context, request, response) => { + console.log('This is the request for create point in time path'); + console.log(request); + const { index } = request.params; + const {keepAlive, allowPartialFailures} = request.query + console.log(index); + console.log(context); + // eslint-disable-next-line @typescript-eslint/naming-convention + debugger; + const client: OpenSearchClient = await getClient(request, context); + + const response_local = await client.createPit({ + index, + keep_alive: keepAlive, + allow_partial_pit_creation: allowPartialFailures + }, + {} + ); + console.log('This is after posting', response_local); + return response.ok({ + body: { + pit_id: response_local.body.pit_id, + creation_time: response_local.body.creation_time, + }, + }); + } + ); +} + +async function getClient( + req: OpenSearchDashboardsRequest< + unknown, + unknown, + Readonly<{} & { dataSourceId: string }>, + 'post' + >, + context: RequestHandlerContext +): Promise { + return req.body.dataSourceId && req.body.dataSourceId !== 'default' && context.dataSource + ? await context.dataSource.opensearch.getClient(req.body.dataSourceId) + : context.core.opensearch.client.asCurrentUser; +} +function trimEnd(arg0: string, arg1: string) { + throw new Error('Function not implemented.'); +} diff --git a/src/plugins/point_in_time_management/server/saved_objects/pit_saved_object.ts b/src/plugins/point_in_time_management/server/saved_objects/pit_saved_object.ts index 40776a530c04..fddb2c1500a3 100644 --- a/src/plugins/point_in_time_management/server/saved_objects/pit_saved_object.ts +++ b/src/plugins/point_in_time_management/server/saved_objects/pit_saved_object.ts @@ -1,40 +1,40 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { SavedObjectsType } from 'opensearch-dashboards/server'; - -export const pointInTimeSavedObject: SavedObjectsType = { - name: 'point-in-time', - namespaceType: 'agnostic', - hidden: false, - management: { - icon: 'apps', // todo: pending ux #2034 - defaultSearchField: 'id', - importableAndExportable: true, - getTitle(obj) { - return obj.attributes.name; - }, - // getEditUrl(obj) { - // return `/management/opensearch-dashboards/dataSources/${encodeURIComponent(obj.id)}`; - // }, - getInAppUrl(obj) { - return { - path: `/app/management/opensearch-dashboards/point-in-time/${encodeURIComponent(obj.id)}`, - uiCapabilitiesPath: 'management.opensearchDashboards.dataSources', - }; - }, - }, - mappings: { - dynamic: false, - properties: { - title: { type: 'text' }, - creation_time: { type: 'double' }, - keepAlive: { type: 'integer' }, - name: { type: 'text' }, - pit_id: { type: 'text' }, - delete_on_expiry: { type: 'boolean' }, - }, - }, -}; +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { SavedObjectsType } from 'opensearch-dashboards/server'; + +export const pointInTimeSavedObject: SavedObjectsType = { + name: 'point-in-time', + namespaceType: 'agnostic', + hidden: false, + management: { + icon: 'apps', // todo: pending ux #2034 + defaultSearchField: 'id', + importableAndExportable: true, + getTitle(obj) { + return obj.attributes.name; + }, + // getEditUrl(obj) { + // return `/management/opensearch-dashboards/dataSources/${encodeURIComponent(obj.id)}`; + // }, + getInAppUrl(obj) { + return { + path: `/app/management/opensearch-dashboards/point-in-time/${encodeURIComponent(obj.id)}`, + uiCapabilitiesPath: 'management.opensearchDashboards.dataSources', + }; + }, + }, + mappings: { + dynamic: false, + properties: { + title: { type: 'text' }, + creation_time: { type: 'double' }, + keepAlive: { type: 'integer' }, + name: { type: 'text' }, + pit_id: { type: 'text' }, + delete_on_expiry: { type: 'boolean' }, + }, + }, +}; diff --git a/yarn.lock b/yarn.lock index 1a037f5af282..029599c4af0f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2338,17 +2338,6 @@ mkdirp "^1.0.4" rimraf "^3.0.2" -"@opensearch-project/opensearch@^2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@opensearch-project/opensearch/-/opensearch-2.1.0.tgz#d79ab4ae643493512099673e117faffe40b4fe56" - integrity sha512-iM2u63j2IlUOuMSbcw1TZFpRqjK6qMwVhb3jLLa/x4aATxdKOiO1i17mgzfkeepqj85efNzXBZzN+jkq1/EXhQ== - dependencies: - aws4 "^1.11.0" - debug "^4.3.1" - hpagent "^0.1.1" - ms "^2.1.3" - secure-json-parse "^2.4.0" - "@opensearch-project/opensearch@^2.2.0": version "2.2.0" resolved "https://registry.yarnpkg.com/@opensearch-project/opensearch/-/opensearch-2.2.0.tgz#2a31a67242bf3bacedc9644a0c68893eb5fb9420" @@ -9641,11 +9630,6 @@ hosted-git-info@^4.0.1: dependencies: lru-cache "^6.0.0" -hpagent@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/hpagent/-/hpagent-0.1.2.tgz#cab39c66d4df2d4377dbd212295d878deb9bdaa9" - integrity sha512-ePqFXHtSQWAFXYmj+JtOTHr84iNrII4/QRlAAPPE+zqnKy4xJo7Ie1Y4kC7AdB+LxLxSTTzBMASsEcy0q8YyvQ== - hpagent@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/hpagent/-/hpagent-1.2.0.tgz#0ae417895430eb3770c03443456b8d90ca464903"