diff --git a/common/constants/shared.ts b/common/constants/shared.ts index f26a598204..9bda5d3be4 100644 --- a/common/constants/shared.ts +++ b/common/constants/shared.ts @@ -58,8 +58,8 @@ export const observabilityIntegrationsID = 'integrations'; export const observabilityIntegrationsTitle = 'Integrations'; export const observabilityIntegrationsPluginOrder = 9020; -export const observabilityDataConnectionsID = 'dataconnections'; -export const observabilityDataConnectionsTitle = 'Data Connections'; +export const observabilityDataConnectionsID = 'datasources'; +export const observabilityDataConnectionsTitle = 'Data sources'; export const observabilityDataConnectionsPluginOrder = 9030; // Shared Constants diff --git a/public/components/app.tsx b/public/components/app.tsx index 7ace523b4f..805ebc2e0c 100644 --- a/public/components/app.tsx +++ b/public/components/app.tsx @@ -19,7 +19,7 @@ import { EventAnalytics } from './event_analytics'; import { Home as MetricsHome } from './metrics/index'; import { Main as NotebooksHome } from './notebooks/components/main'; import { Home as TraceAnalyticsHome } from './trace_analytics/home'; -import { Home as DataConnectionsHome } from './data_connections/home'; +import { Home as DataConnectionsHome } from './datasources/home'; interface ObservabilityAppDeps { CoreStartProp: CoreStart; diff --git a/public/components/data_connections/components/data_connections_header.tsx b/public/components/data_connections/components/data_connections_header.tsx deleted file mode 100644 index 7f071683b4..0000000000 --- a/public/components/data_connections/components/data_connections_header.tsx +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - EuiLink, - EuiPageHeader, - EuiPageHeaderSection, - EuiSpacer, - EuiText, - EuiTitle, -} from '@elastic/eui'; -import _ from 'lodash'; -import React from 'react'; -import { OPENSEARCH_DOCUMENTATION_URL } from '../../../../common/constants/data_connections'; - -export const DataConnectionsHeader = () => { - return ( -
- - - -

Data connections

-
-
-
- - - Connect and manage compatible OpenSearch and OpenSearch Dashboard data connections.{' '} - - Learn more - - - -
- ); -}; diff --git a/public/components/data_connections/components/__tests__/__snapshots__/data_connection.test.tsx.snap b/public/components/datasources/components/__tests__/__snapshots__/data_connection.test.tsx.snap similarity index 100% rename from public/components/data_connections/components/__tests__/__snapshots__/data_connection.test.tsx.snap rename to public/components/datasources/components/__tests__/__snapshots__/data_connection.test.tsx.snap diff --git a/public/components/data_connections/components/__tests__/__snapshots__/manage_data_connections_description.test.tsx.snap b/public/components/datasources/components/__tests__/__snapshots__/manage_data_connections_description.test.tsx.snap similarity index 91% rename from public/components/data_connections/components/__tests__/__snapshots__/manage_data_connections_description.test.tsx.snap rename to public/components/datasources/components/__tests__/__snapshots__/manage_data_connections_description.test.tsx.snap index 2cc84b45b3..10c1b24841 100644 --- a/public/components/data_connections/components/__tests__/__snapshots__/manage_data_connections_description.test.tsx.snap +++ b/public/components/datasources/components/__tests__/__snapshots__/manage_data_connections_description.test.tsx.snap @@ -9,7 +9,7 @@ exports[`Manage Data Connections Description test Renders manage data connection

- Manage existing data connections + Manage existing data sources

- Manage already created data connections. + Manage already created data sources. diff --git a/public/components/data_connections/components/__tests__/__snapshots__/manage_data_connections_table.test.tsx.snap b/public/components/datasources/components/__tests__/__snapshots__/manage_data_connections_table.test.tsx.snap similarity index 96% rename from public/components/data_connections/components/__tests__/__snapshots__/manage_data_connections_table.test.tsx.snap rename to public/components/datasources/components/__tests__/__snapshots__/manage_data_connections_table.test.tsx.snap index 20c8473401..6cd9a84f91 100644 --- a/public/components/data_connections/components/__tests__/__snapshots__/manage_data_connections_table.test.tsx.snap +++ b/public/components/datasources/components/__tests__/__snapshots__/manage_data_connections_table.test.tsx.snap @@ -19,7 +19,7 @@ exports[`Manage Data Connections Table test Renders manage data connections tabl class="euiTitle euiTitle--large" data-test-subj="dataconnections-header" > - Data connections + Data sources @@ -32,7 +32,7 @@ exports[`Manage Data Connections Table test Renders manage data connections tabl
- Connect and manage compatible OpenSearch and OpenSearch Dashboard data connections. + Connect and manage compatible OpenSearch and OpenSearch Dashboard data sources. +
+ + +
+
- Manage existing data connections + Manage existing data sources
- Manage already created data connections. + Manage already created data sources.

({ diff --git a/public/components/data_connections/components/__tests__/manage_data_connections_description.test.tsx b/public/components/datasources/components/__tests__/manage_data_connections_description.test.tsx similarity index 86% rename from public/components/data_connections/components/__tests__/manage_data_connections_description.test.tsx rename to public/components/datasources/components/__tests__/manage_data_connections_description.test.tsx index 6862306831..3bbfa820e6 100644 --- a/public/components/data_connections/components/__tests__/manage_data_connections_description.test.tsx +++ b/public/components/datasources/components/__tests__/manage_data_connections_description.test.tsx @@ -7,7 +7,7 @@ import { configure, mount } from 'enzyme'; import Adapter from 'enzyme-adapter-react-16'; import { waitFor } from '@testing-library/react'; import React from 'react'; -import { DataConnectionsDescription } from '../manage_data_connections_description'; +import { DataConnectionsDescription } from '../manage/manage_data_connections_description'; describe('Manage Data Connections Description test', () => { configure({ adapter: new Adapter() }); diff --git a/public/components/data_connections/components/__tests__/manage_data_connections_table.test.tsx b/public/components/datasources/components/__tests__/manage_data_connections_table.test.tsx similarity index 92% rename from public/components/data_connections/components/__tests__/manage_data_connections_table.test.tsx rename to public/components/datasources/components/__tests__/manage_data_connections_table.test.tsx index cd5509f1b8..dfdb65d858 100644 --- a/public/components/data_connections/components/__tests__/manage_data_connections_table.test.tsx +++ b/public/components/datasources/components/__tests__/manage_data_connections_table.test.tsx @@ -7,7 +7,7 @@ import { configure } from 'enzyme'; import Adapter from 'enzyme-adapter-react-16'; import { act } from '@testing-library/react'; import React from 'react'; -import { ManageDataConnectionsTable } from '../manage_data_connections_table'; +import { ManageDataConnectionsTable } from '../manage/manage_data_connections_table'; import { showDataConnectionsData } from '../../../../../test/datasources'; import ReactDOM from 'react-dom'; diff --git a/public/components/datasources/components/data_connections_header.tsx b/public/components/datasources/components/data_connections_header.tsx new file mode 100644 index 0000000000..85f204dd9b --- /dev/null +++ b/public/components/datasources/components/data_connections_header.tsx @@ -0,0 +1,77 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { + EuiLink, + EuiPageHeader, + EuiPageHeaderSection, + EuiSpacer, + EuiTab, + EuiTabs, + EuiText, + EuiTitle, +} from '@elastic/eui'; +import _ from 'lodash'; +import React, { useState } from 'react'; +import { OPENSEARCH_DOCUMENTATION_URL } from '../../../../common/constants/data_connections'; + +export const DataConnectionsHeader = () => { + const tabs = [ + { + id: 'manage', + name: 'Manage data source', + disabled: false, + }, + { + id: 'new', + name: 'New data source', + disabled: false, + }, + ]; + + const [selectedTabId, setSelectedTabId] = useState( + window.location.hash.substring(2) ? window.location.hash.substring(2) : 'manage' + ); + + const onSelectedTabChanged = (id) => { + setSelectedTabId(id); + window.location.hash = id; + }; + + const renderTabs = () => { + return tabs.map((tab, index) => ( + onSelectedTabChanged(tab.id)} + isSelected={tab.id === selectedTabId} + disabled={tab.disabled} + key={index} + > + {tab.name} + + )); + }; + + return ( +
+ + + +

Data sources

+
+
+
+ + + Connect and manage compatible OpenSearch and OpenSearch Dashboard data sources.{' '} + + Learn more + + + + {renderTabs()} + +
+ ); +}; diff --git a/public/components/data_connections/components/access_control_tab.tsx b/public/components/datasources/components/manage/access_control_tab.tsx similarity index 90% rename from public/components/data_connections/components/access_control_tab.tsx rename to public/components/datasources/components/manage/access_control_tab.tsx index 58fdffde33..d35f3876f0 100644 --- a/public/components/data_connections/components/access_control_tab.tsx +++ b/public/components/datasources/components/manage/access_control_tab.tsx @@ -14,15 +14,16 @@ import { import React, { useEffect, useState } from 'react'; import { EuiPanel } from '@elastic/eui'; import { ConnectionManagementCallout } from './connection_management_callout'; -import { coreRefs } from '../../../../public/framework/core_refs'; +import { coreRefs } from '../../../../framework/core_refs'; import { QueryPermissionsConfiguration } from './query_permissions'; -import { DATACONNECTIONS_BASE } from '../../../../common/constants/shared'; -import { SaveOrCancel } from './save_or_cancel'; +import { DATACONNECTIONS_BASE } from '../../../../../common/constants/shared'; +import { SaveOrCancel } from '../save_or_cancel'; interface AccessControlTabProps { dataConnection: string; connector: string; properties: unknown; + allowedRoles: string[]; } export const AccessControlTab = (props: AccessControlTabProps) => { @@ -30,7 +31,11 @@ export const AccessControlTab = (props: AccessControlTabProps) => { const [roles, setRoles] = useState>([]); const [selectedQueryPermissionRoles, setSelectedQueryPermissionRoles] = useState< Array<{ label: string }> - >([]); + >( + props.allowedRoles.map((role) => { + return { label: role }; + }) + ); const { http } = coreRefs; useEffect(() => { @@ -51,7 +56,7 @@ export const AccessControlTab = (props: AccessControlTabProps) => { Query access - {[].length ? `Restricted` : '-'} + {selectedQueryPermissionRoles.length ? `Restricted` : '-'} diff --git a/public/components/data_connections/components/connection_configuration.tsx b/public/components/datasources/components/manage/connection_configuration.tsx similarity index 100% rename from public/components/data_connections/components/connection_configuration.tsx rename to public/components/datasources/components/manage/connection_configuration.tsx diff --git a/public/components/data_connections/components/connection_details.tsx b/public/components/datasources/components/manage/connection_details.tsx similarity index 96% rename from public/components/data_connections/components/connection_details.tsx rename to public/components/datasources/components/manage/connection_details.tsx index 44cd206f43..5330719602 100644 --- a/public/components/data_connections/components/connection_details.tsx +++ b/public/components/datasources/components/manage/connection_details.tsx @@ -14,9 +14,9 @@ import { import React, { useState } from 'react'; import { EuiPanel } from '@elastic/eui'; import { ConnectionManagementCallout } from './connection_management_callout'; -import { coreRefs } from '../../../../public/framework/core_refs'; -import { DATACONNECTIONS_BASE } from '../../../../common/constants/shared'; -import { SaveOrCancel } from './save_or_cancel'; +import { coreRefs } from '../../../../framework/core_refs'; +import { DATACONNECTIONS_BASE } from '../../../../../common/constants/shared'; +import { SaveOrCancel } from '../save_or_cancel'; import { ConnectionConfiguration } from './connection_configuration'; interface ConnectionDetailProps { diff --git a/public/components/data_connections/components/connection_management_callout.tsx b/public/components/datasources/components/manage/connection_management_callout.tsx similarity index 100% rename from public/components/data_connections/components/connection_management_callout.tsx rename to public/components/datasources/components/manage/connection_management_callout.tsx diff --git a/public/components/data_connections/components/data_connection.tsx b/public/components/datasources/components/manage/data_connection.tsx similarity index 93% rename from public/components/data_connections/components/data_connection.tsx rename to public/components/datasources/components/manage/data_connection.tsx index d4c87ef495..a0527e7bc2 100644 --- a/public/components/data_connections/components/data_connection.tsx +++ b/public/components/datasources/components/manage/data_connection.tsx @@ -21,9 +21,9 @@ import { } from '@elastic/eui'; import React, { useEffect, useState } from 'react'; import { AccessControlTab } from './access_control_tab'; -import { NoAccess } from './no_access'; -import { DATACONNECTIONS_BASE } from '../../../../common/constants/shared'; -import { coreRefs } from '../../../../public/framework/core_refs'; +import { NoAccess } from '../no_access'; +import { DATACONNECTIONS_BASE } from '../../../../../common/constants/shared'; +import { coreRefs } from '../../../../framework/core_refs'; import { ConnectionDetails } from './connection_details'; interface DatasourceDetails { @@ -49,7 +49,7 @@ export const DataConnection = (props: any) => { useEffect(() => { chrome!.setBreadcrumbs([ { - text: 'Data Connections', + text: 'Data sources', href: '#/', }, { @@ -59,15 +59,15 @@ export const DataConnection = (props: any) => { ]); http! .get(`${DATACONNECTIONS_BASE}/${dataSource}`) - .then((data) => + .then((data) => { setDatasourceDetails({ allowedRoles: data.allowedRoles, name: data.name, cluster: data.properties['emr.cluster'], connector: data.connector, properties: data.properties, - }) - ) + }); + }) .catch((err) => { setHasAccess(false); }); @@ -80,9 +80,11 @@ export const DataConnection = (props: any) => { disabled: false, content: ( ), }, @@ -200,7 +202,7 @@ export const DataConnection = (props: any) => { - + diff --git a/public/components/data_connections/components/manage_data_connections_description.tsx b/public/components/datasources/components/manage/manage_data_connections_description.tsx similarity index 82% rename from public/components/data_connections/components/manage_data_connections_description.tsx rename to public/components/datasources/components/manage/manage_data_connections_description.tsx index 26cfa90cc8..866ac5ae30 100644 --- a/public/components/data_connections/components/manage_data_connections_description.tsx +++ b/public/components/datasources/components/manage/manage_data_connections_description.tsx @@ -10,12 +10,12 @@ export const DataConnectionsDescription = () => { return (
-

Manage existing data connections

+

Manage existing data sources

- Manage already created data connections. + Manage already created data sources.
diff --git a/public/components/data_connections/components/manage_data_connections_table.tsx b/public/components/datasources/components/manage/manage_data_connections_table.tsx similarity index 92% rename from public/components/data_connections/components/manage_data_connections_table.tsx rename to public/components/datasources/components/manage/manage_data_connections_table.tsx index e1950e704a..5f223ae03d 100644 --- a/public/components/data_connections/components/manage_data_connections_table.tsx +++ b/public/components/datasources/components/manage/manage_data_connections_table.tsx @@ -17,12 +17,12 @@ import { } from '@elastic/eui'; import _ from 'lodash'; import React, { useEffect, useState } from 'react'; -import { DataConnectionsHeader } from './data_connections_header'; -import { HomeProps } from '../home'; +import { DataConnectionsHeader } from '../data_connections_header'; +import { HomeProps } from '../../home'; import { DataConnectionsDescription } from './manage_data_connections_description'; -import { DATACONNECTIONS_BASE } from '../../../../common/constants/shared'; -import { useToast } from '../../../../public/components/common/toast'; -import { DeleteModal } from '../../../../public/components/common/helpers/delete_modal'; +import { DATACONNECTIONS_BASE } from '../../../../../common/constants/shared'; +import { useToast } from '../../../common/toast'; +import { DeleteModal } from '../../../common/helpers/delete_modal'; interface DataConnection { connectionType: 'OPENSEARCH' | 'SPARK'; @@ -57,7 +57,7 @@ export const ManageDataConnectionsTable = (props: HomeProps) => { useEffect(() => { chrome.setBreadcrumbs([ { - text: 'Data Connections', + text: 'Data sources', href: '#/', }, ]); diff --git a/public/components/data_connections/components/query_permissions.tsx b/public/components/datasources/components/manage/query_permissions.tsx similarity index 94% rename from public/components/data_connections/components/query_permissions.tsx rename to public/components/datasources/components/manage/query_permissions.tsx index eee8312a8e..25f43ffacb 100644 --- a/public/components/data_connections/components/query_permissions.tsx +++ b/public/components/datasources/components/manage/query_permissions.tsx @@ -17,8 +17,8 @@ import { OPENSEARCH_DOCUMENTATION_URL, QUERY_ALL, QUERY_RESTRICTED, -} from '../../../../common/constants/data_connections'; -import { PermissionsConfigurationProps } from '../../../../common/types/data_connections'; +} from '../../../../../common/constants/data_connections'; +import { PermissionsConfigurationProps } from '../../../../../common/types/data_connections'; export const QueryPermissionsConfiguration = (props: PermissionsConfigurationProps) => { const { roles, selectedRoles, setSelectedRoles } = props; diff --git a/public/components/datasources/components/new/configure_datasource.tsx b/public/components/datasources/components/new/configure_datasource.tsx new file mode 100644 index 0000000000..ed44498c84 --- /dev/null +++ b/public/components/datasources/components/new/configure_datasource.tsx @@ -0,0 +1,211 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { + EuiFlexGroup, + EuiFlexItem, + EuiPage, + EuiPageBody, + EuiSpacer, + EuiTitle, + EuiText, + EuiLink, + EuiButton, + EuiSteps, + EuiPageSideBar, + EuiPanel, + EuiFormRow, + EuiFieldText, + EuiBottomBar, + EuiButtonEmpty, + EuiTextArea, +} from '@elastic/eui'; +import React, { useCallback, useEffect, useState } from 'react'; +import { ConfigureS3Datasource } from './configure_s3_datasource'; +import { coreRefs } from '../../../../../public/framework/core_refs'; +import { DATACONNECTIONS_BASE } from '../../../../../common/constants/shared'; +import { ReviewS3Datasource } from './review_s3_datasource_configuration'; +import { useToast } from '../../../../../public/components/common/toast'; + +interface ConfigureDatasourceProps { + type: string; +} + +export function Configure(props: ConfigureDatasourceProps) { + const { type } = props; + const { http } = coreRefs; + const { setToast } = useToast(); + + const [name, setName] = useState(''); + const [details, setDetails] = useState(''); + const [arn, setArn] = useState(''); + const [store, setStore] = useState(''); + const [roles, setRoles] = useState>([]); + const [selectedQueryPermissionRoles, setSelectedQueryPermissionRoles] = useState< + Array<{ label: string }> + >([]); + const [page, setPage] = useState<'configure' | 'review'>('configure'); + const ConfigureDatasourceSteps = [ + { + title: 'Step 1', + children: ( + +

Configure Connection

+
+ ), + }, + { + title: 'Step 2', + children: ( + +

Review Configuration

+
+ ), + }, + ]; + + useEffect(() => { + http!.get('/api/v1/configuration/roles').then((data) => + setRoles( + Object.keys(data.data).map((key) => { + return { label: key }; + }) + ) + ); + }, []); + + const ConfigureDatasource = (configurationProps: { datasourceType: string }) => { + const { datasourceType } = configurationProps; + switch (datasourceType) { + case 'S3': + return ( + + ); + default: + return <>; + } + }; + + const ReviewDatasourceConfiguration = (configurationProps: { datasourceType: string }) => { + const { datasourceType } = configurationProps; + switch (datasourceType) { + case 'S3': + return ( + + ); + default: + return <>; + } + }; + + const ReviewSaveOrCancel = useCallback(() => { + return ( + + + + { + window.location.hash = '#/new'; + }} + color="ghost" + size="s" + iconType="cross" + > + Cancel + + + + setPage('configure') : () => {}} + color="ghost" + size="s" + iconType="arrowLeft" + > + Previous + + + + createDatasource() + : () => { + setPage('review'); + } + } + size="s" + iconType="arrowRight" + fill + > + {page === 'configure' ? `Review Configuration` : `Connect to ${type}`} + + + + + ); + }, [page]); + + const createDatasource = () => { + http! + .post(`${DATACONNECTIONS_BASE}`, { + body: JSON.stringify({ + name, + allowedRoles: selectedQueryPermissionRoles.map((role) => role.label), + connector: 's3glue', + properties: { + 'glue.auth.type': 'iam_role', + 'glue.auth.role_arn': arn, + 'glue.indexstore.opensearch.uri': store, + 'glue.indexstore.opensearch.auth': false, + 'glue.indexstore.opensearch.region': 'us-west-2', + }, + }), + }) + .then(() => { + setToast(`Data source ${name} created successfully!`); + window.location.hash = '#/manage'; + }) + .catch((err) => { + setToast(`Data source ${name} created successfully!`); + window.location.hash = '#/manage'; + }); + }; + + return ( + + + + + + {page === 'configure' ? ( + + ) : ( + + )} + + + + + + ); +} diff --git a/public/components/datasources/components/new/configure_s3_datasource.tsx b/public/components/datasources/components/new/configure_s3_datasource.tsx new file mode 100644 index 0000000000..155d29d40d --- /dev/null +++ b/public/components/datasources/components/new/configure_s3_datasource.tsx @@ -0,0 +1,204 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { + EuiPanel, + EuiTitle, + EuiSpacer, + EuiText, + EuiLink, + EuiFormRow, + EuiFieldText, + EuiTextArea, + EuiButton, +} from '@elastic/eui'; +import React, { useState } from 'react'; +import { OPENSEARCH_DOCUMENTATION_URL } from '../../../../../common/constants/data_connections'; +import { QueryPermissionsConfiguration } from '../manage/query_permissions'; + +interface ConfigureS3DatasourceProps { + roles: Array<{ label: string }>; + selectedQueryPermissionRoles: Array<{ label: string }>; + setSelectedQueryPermissionRoles: React.Dispatch>>; + currentName: string; + currentDetails: string; + currentArn: string; + currentStore: string; + setStoreForRequest: React.Dispatch>; + setNameForRequest: React.Dispatch>; + setDetailsForRequest: React.Dispatch>; + setArnForRequest: React.Dispatch>; +} + +export const ConfigureS3Datasource = (props: ConfigureS3DatasourceProps) => { + const { + setNameForRequest, + setDetailsForRequest, + setArnForRequest, + setStoreForRequest, + currentStore, + currentName, + currentDetails, + currentArn, + roles, + selectedQueryPermissionRoles, + setSelectedQueryPermissionRoles, + } = props; + + const [name, setName] = useState(currentName); + const [details, setDetails] = useState(currentDetails); + const [arn, setArn] = useState(currentArn); + const [store, setStore] = useState(currentStore); + + return ( +
+ + +

{`Configure S3 Data Source`}

+
+ + + {`Connect to S3with OpenSearch and OpenSearch Dashboards `} + + Learn more + + + + +

Data source details

+
+ + + <> + +

+ This is the name the connection will be referenced by in OpenSearch Dashboards. It + is recommended to make this short yet descriptive to help users when selecting a + connection. +

+
+ { + setName(e.target.value); + }} + onBlur={(e) => { + setNameForRequest(e.target.value); + }} + /> + +
+ + { + setDetailsForRequest(e.target.value); + }} + onChange={(e) => { + setDetails(e.target.value); + }} + /> + + + + +

Glue authentication details

+
+ + + + <> + +

+ This parameters provides the authentication type information required for execution + engine to connect to glue. +

+
+ + +
+ + + <> + +

This should be the IAM role ARN

+
+ { + setArn(e.target.value); + }} + onBlur={(e) => { + setArnForRequest(e.target.value); + }} + /> + +
+ + + + +

Glue index store details

+
+ + + + <> + +

+ This parameters provides the OpenSearch cluster host information for glue. This + OpenSearch instance is used for writing index data back. +

+
+ { + setStore(e.target.value); + }} + onBlur={(e) => { + setStoreForRequest(e.target.value); + }} + /> + +
+ + + <> + +

Lorem ipsum.

+
+ + +
+ + + <> + +

Lorem ipsum.

+
+ + +
+ + Test connection + + + + +
+
+ ); +}; diff --git a/public/components/datasources/components/new/new_datasource.tsx b/public/components/datasources/components/new/new_datasource.tsx new file mode 100644 index 0000000000..c504a2c101 --- /dev/null +++ b/public/components/datasources/components/new/new_datasource.tsx @@ -0,0 +1,48 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { EuiPage, EuiPageBody } from '@elastic/eui'; +import _ from 'lodash'; +import React, { useEffect, useState } from 'react'; +import { DataConnectionsHeader } from '../data_connections_header'; +import { HomeProps } from '../../home'; +import { AvailableIntegrationsList } from '../../../integrations/components/available_integration_overview_page'; +import { NewDatasourceCardView } from './new_datasource_card_view'; + +interface DataConnection { + connectionType: 'OPENSEARCH' | 'SPARK'; + name: string; +} + +export const NewDatasource = (props: HomeProps) => { + const { chrome, http } = props; + + // TODO: implement searching the card view with this + const [query, setQuery] = useState(''); + const [isCardView, setCardView] = useState(true); + + useEffect(() => { + chrome.setBreadcrumbs([ + { + text: 'Data sources', + href: '#/', + }, + ]); + }, []); + + // TODO: implement table view + const NewDatasourceTableView = () => { + return null; + }; + + return ( + + + + {isCardView ? : } + + + ); +}; diff --git a/public/components/datasources/components/new/new_datasource_card_view.tsx b/public/components/datasources/components/new/new_datasource_card_view.tsx new file mode 100644 index 0000000000..727975a5c0 --- /dev/null +++ b/public/components/datasources/components/new/new_datasource_card_view.tsx @@ -0,0 +1,115 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { + EuiPanel, + EuiCard, + EuiFlexGroup, + EuiFlexItem, + EuiSpacer, + EuiFieldSearch, + EuiButtonGroup, + EuiIcon, +} from '@elastic/eui'; +import _ from 'lodash'; +import React, { useState } from 'react'; +import { NewDatasourceDescription } from './new_datasource_description'; +import { coreRefs } from '../../../../framework/core_refs'; +import sparkSvg from '../../icons/apache_spark-icon.svg'; +import s3Svg from '../../icons/s3-logo.svg'; + +export interface DatasourceType { + name: string; + description: string; + displayIcon: JSX.Element; +} + +const Datasources: DatasourceType[] = [ + { + name: 'OpenSearch', + description: 'Connect to self managed OpenSearch clusters', + displayIcon: , + }, + { + name: 'S3', + description: 'Connect to Amazon S3 via Amazon Glue', + displayIcon: , + }, +]; + +export function NewDatasourceCardView() { + const { http } = coreRefs; + const [toggleIconIdSelected, setToggleIconIdSelected] = useState('1'); + + const toggleButtonsIcons = [ + { + id: '0', + label: 'list', + iconType: 'list', + }, + { + id: '1', + label: 'grid', + iconType: 'grid', + }, + ]; + + const onChangeIcons = (optionId: string) => { + setToggleIconIdSelected(optionId); + }; + + const renderRows = (datasources: DatasourceType[]) => { + return ( + <> + + {datasources.map((i, v) => { + return ( + + (window.location.hash = `#/configure/${i.name}`)} + /> + + ); + })} + + + + ); + }; + + return ( + + + + + {}} + /> + + + onChangeIcons(id)} + isIconOnly + /> + + + + {renderRows(Datasources)} + + ); +} diff --git a/public/components/datasources/components/new/new_datasource_description.tsx b/public/components/datasources/components/new/new_datasource_description.tsx new file mode 100644 index 0000000000..91f13c6662 --- /dev/null +++ b/public/components/datasources/components/new/new_datasource_description.tsx @@ -0,0 +1,24 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { EuiSpacer, EuiText, EuiTitle, EuiHorizontalRule } from '@elastic/eui'; +import React from 'react'; + +export const NewDatasourceDescription = () => { + return ( +
+ +

Create a new data source

+
+ + + + Connect to a compatible data source or compute engine to bring your data into OpenSearch and + OpenSearch Dashboards. + + +
+ ); +}; diff --git a/public/components/datasources/components/new/review_s3_datasource_configuration.tsx b/public/components/datasources/components/new/review_s3_datasource_configuration.tsx new file mode 100644 index 0000000000..ede85f204d --- /dev/null +++ b/public/components/datasources/components/new/review_s3_datasource_configuration.tsx @@ -0,0 +1,103 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { + EuiPanel, + EuiTitle, + EuiSpacer, + EuiText, + EuiLink, + EuiFormRow, + EuiFieldText, + EuiTextArea, + EuiButton, + EuiFlexGroup, + EuiHorizontalRule, + EuiFlexItem, +} from '@elastic/eui'; +import React, { useState } from 'react'; +import { OPENSEARCH_DOCUMENTATION_URL } from '../../../../../common/constants/data_connections'; +import { QueryPermissionsConfiguration } from '../manage/query_permissions'; + +interface ConfigureS3DatasourceProps { + selectedQueryPermissionRoles: Array<{ label: string }>; + currentName: string; + currentDetails: string; + currentArn: string; + currentStore: string; +} + +export const ReviewS3Datasource = (props: ConfigureS3DatasourceProps) => { + const { + currentStore, + currentName, + currentDetails, + currentArn, + selectedQueryPermissionRoles, + } = props; + + return ( +
+ + +

{`Review S3 Data Source Configuration`}

+
+ + + +

Data source configuration

+
+ + + + + + + Data source name + + {currentName} + + + + Description + + {currentDetails} + + + + + + + + Glue authentication ARN + + {currentArn} + + + + Glue index store URI + + {currentStore} + + + + + + + + Query Permissions + + {selectedQueryPermissionRoles + ? `Restricted - ${JSON.stringify(selectedQueryPermissionRoles)}` + : 'Everyone'} + + + + + +
+
+ ); +}; diff --git a/public/components/data_connections/components/no_access.tsx b/public/components/datasources/components/no_access.tsx similarity index 100% rename from public/components/data_connections/components/no_access.tsx rename to public/components/datasources/components/no_access.tsx diff --git a/public/components/data_connections/components/save_or_cancel.tsx b/public/components/datasources/components/save_or_cancel.tsx similarity index 100% rename from public/components/data_connections/components/save_or_cancel.tsx rename to public/components/datasources/components/save_or_cancel.tsx diff --git a/public/components/data_connections/home.tsx b/public/components/datasources/home.tsx similarity index 64% rename from public/components/data_connections/home.tsx rename to public/components/datasources/home.tsx index 29d5e83bda..fef07a7803 100644 --- a/public/components/data_connections/home.tsx +++ b/public/components/datasources/home.tsx @@ -6,8 +6,10 @@ import React from 'react'; import { HashRouter, Route, RouteComponentProps, Switch } from 'react-router-dom'; import { ChromeBreadcrumb, ChromeStart, HttpStart } from '../../../../../src/core/public'; -import { DataConnection } from './components/data_connection'; -import { ManageDataConnectionsTable } from './components/manage_data_connections_table'; +import { DataConnection } from './components/manage/data_connection'; +import { ManageDataConnectionsTable } from './components/manage/manage_data_connections_table'; +import { NewDatasource } from './components/new/new_datasource'; +import { Configure } from './components/new/configure_datasource'; export interface HomeProps extends RouteComponentProps { pplService: any; @@ -44,6 +46,15 @@ export const Home = (props: HomeProps) => { path={['/', '/manage']} render={(routerProps) => } /> + } /> + + ( + + )} + /> ); diff --git a/public/components/datasources/icons/apache_spark-icon.svg b/public/components/datasources/icons/apache_spark-icon.svg new file mode 100644 index 0000000000..30ba2b1823 --- /dev/null +++ b/public/components/datasources/icons/apache_spark-icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/components/datasources/icons/s3-logo.svg b/public/components/datasources/icons/s3-logo.svg new file mode 100644 index 0000000000..39b0fc099a --- /dev/null +++ b/public/components/datasources/icons/s3-logo.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/server/adaptors/ppl_plugin.ts b/server/adaptors/ppl_plugin.ts index 563c436726..6007f913f1 100644 --- a/server/adaptors/ppl_plugin.ts +++ b/server/adaptors/ppl_plugin.ts @@ -68,6 +68,14 @@ export const PPLPlugin = function (Client, config, components) { method: 'DELETE', }); + ppl.createDataSource = ca({ + url: { + fmt: `${OPENSEARCH_DATACONNECTIONS_API.DATACONNECTION}`, + }, + needBody: true, + method: 'POST', + }); + ppl.modifyDataConnection = ca({ url: { fmt: `${OPENSEARCH_DATACONNECTIONS_API.DATACONNECTION}`, diff --git a/server/routes/data_connections/data_connections_router.ts b/server/routes/data_connections/data_connections_router.ts index a65660ba4a..2c996ddcc1 100644 --- a/server/routes/data_connections/data_connections_router.ts +++ b/server/routes/data_connections/data_connections_router.ts @@ -103,6 +103,43 @@ export function registerDataConnectionsRoute(router: IRouter) { } ); + router.post( + { + path: `${DATACONNECTIONS_BASE}`, + validate: { + body: schema.object({ + name: schema.string(), + connector: schema.string(), + allowedRoles: schema.arrayOf(schema.string()), + properties: schema.any(), + }), + }, + }, + async (context, request, response): Promise => { + try { + const dataConnectionsresponse = await context.observability_plugin.observabilityClient + .asScoped(request) + .callAsCurrentUser('ppl.createDataSource', { + body: { + name: request.body.name, + connector: request.body.connector, + allowedRoles: request.body.allowedRoles, + properties: request.body.properties, + }, + }); + return response.ok({ + body: dataConnectionsresponse, + }); + } catch (error: any) { + console.error('Issue in creating data source:', error); + return response.custom({ + statusCode: error.statusCode || 500, + body: error.message, + }); + } + } + ); + router.get( { path: `${DATACONNECTIONS_BASE}`,