Skip to content

Commit

Permalink
Merge branch 'opensearch-project:main' into metrics-aos-2.9
Browse files Browse the repository at this point in the history
  • Loading branch information
kavithacm authored Aug 3, 2023
2 parents 2e2ef6a + 4d33d82 commit 589d6f5
Show file tree
Hide file tree
Showing 23 changed files with 1,047 additions and 134 deletions.
4 changes: 0 additions & 4 deletions common/constants/integrations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,3 @@

export const OPENSEARCH_DOCUMENTATION_URL = 'https://opensearch.org/docs/latest/integrations/index';
export const ASSET_FILTER_OPTIONS = ['index-pattern', 'search', 'visualization', 'dashboard'];
// TODO get this list dynamically from the API
export const INTEGRATION_TEMPLATE_OPTIONS = ['nginx'];
// TODO get this list dynamically from the API
export const INTEGRATION_CATEOGRY_OPTIONS = ['communication', 'http', 'cloud', 'container', 'logs'];
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ export const doPropertyValidation = (
};

export function AddIntegrationFlyout(props: IntegrationFlyoutProps) {
const { onClose, onCreate, integrationName, integrationType } = props;
const { onClose, onCreate, integrationName, integrationType, http } = props;

const [isDataSourceValid, setDataSourceValid] = useState<null | false | true>(null);

Expand Down Expand Up @@ -131,11 +131,13 @@ export function AddIntegrationFlyout(props: IntegrationFlyoutProps) {
const fetchDataSourceMappings = async (
targetDataSource: string
): Promise<{ [key: string]: { properties: any } } | null> => {
return fetch(`/api/console/proxy?path=${targetDataSource}/_mapping&method=GET`, {
method: 'POST',
headers: [['osd-xsrf', 'true']],
})
.then((response) => response.json())
return http
.post('/api/console/proxy', {
query: {
path: `${targetDataSource}/_mapping`,
method: 'GET',
},
})
.then((response) => {
// Un-nest properties by a level for caller convenience
Object.keys(response).forEach((key) => {
Expand All @@ -152,8 +154,8 @@ export function AddIntegrationFlyout(props: IntegrationFlyoutProps) {
const fetchIntegrationMappings = async (
targetName: string
): Promise<{ [key: string]: { template: { mappings: { properties?: any } } } } | null> => {
return fetch(`/api/integrations/repository/${targetName}/schema`)
.then((response) => response.json())
return http
.get(`/api/integrations/repository/${targetName}/schema`)
.then((response) => {
if (response.statusCode && response.statusCode !== 200) {
throw new Error('Failed to retrieve Integration schema', { cause: response });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { HttpStart } from '../../../../../../src/core/public';
export interface AddedIntegrationsTableProps {
loading: boolean;
data: AddedIntegrationsList;
setData: React.Dispatch<React.SetStateAction<AddedIntegrationsList>>;
http: HttpStart;
}

Expand Down Expand Up @@ -57,7 +58,7 @@ export function AddedIntegrationOverviewPage(props: AddedIntegrationOverviewPage
<EuiPage>
<EuiPageBody component="div">
{IntegrationHeader()}
{AddedIntegrationsTable({ data, loading: false, http })}
{AddedIntegrationsTable({ data, setData, loading: false, http })}
</EuiPageBody>
</EuiPage>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,11 @@ import {
import _ from 'lodash';
import React, { useState } from 'react';
import { AddedIntegrationsTableProps } from './added_integration_overview_page';
import {
ASSET_FILTER_OPTIONS,
INTEGRATION_TEMPLATE_OPTIONS,
} from '../../../../common/constants/integrations';
import { DeleteModal } from '../../../../public/components/common/helpers/delete_modal';
import { INTEGRATIONS_BASE } from '../../../../common/constants/shared';
import { useToast } from '../../../../public/components/common/toast';

export function AddedIntegrationsTable(props: AddedIntegrationsTableProps) {
const integrations = props.data.hits;

const { http } = props;

const { setToast } = useToast();
Expand Down Expand Up @@ -94,6 +88,9 @@ export function AddedIntegrationsTable(props: AddedIntegrationsTableProps) {
.delete(`${INTEGRATIONS_BASE}/store/${integrationInstance}`)
.then(() => {
setToast(`${name} integration successfully deleted!`, 'success');
props.setData({
hits: props.data.hits.filter((i) => i.id !== integrationInstance),
});
})
.catch((err) => {
setToast(`Error deleting ${name} or its assets`, 'danger');
Expand All @@ -103,7 +100,7 @@ export function AddedIntegrationsTable(props: AddedIntegrationsTableProps) {
});
}

const getModal = (integrationInstanceId, name) => {
const getModal = (integrationInstanceId: string, name: string) => {
setModalLayout(
<DeleteModal
onConfirm={() => {
Expand All @@ -120,26 +117,28 @@ export function AddedIntegrationsTable(props: AddedIntegrationsTableProps) {
setIsModalVisible(true);
};

const integTemplateNames = [...new Set(integrations.map((i) => i.templateName))].sort();

const search = {
box: {
incremental: true,
},
filters: [
{
type: 'field_value_selection',
type: 'field_value_selection' as const,
field: 'templateName',
name: 'Type',
multiSelect: false,
options: INTEGRATION_TEMPLATE_OPTIONS.map((i) => ({
value: i,
name: i,
view: i,
options: integTemplateNames.map((name) => ({
name,
value: name,
view: name,
})),
},
],
};

const entries = integrations.map((integration) => {
const entries = props.data.hits.map((integration) => {
const id = integration.id;
const templateName = integration.templateName;
const creationDate = integration.creationDate;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { INTEGRATIONS_BASE } from '../../../../common/constants/shared';
import { badges } from './integration_category_badge_group';

export function AvailableIntegrationsCardView(props: AvailableIntegrationsCardViewProps) {
const http = props.http;
const [toggleIconIdSelected, setToggleIconIdSelected] = useState('1');

const getImage = (url?: string) => {
Expand Down Expand Up @@ -72,7 +73,9 @@ export function AvailableIntegrationsCardView(props: AvailableIntegrationsCardVi
<EuiFlexItem key={v} style={{ minWidth: '14rem', maxWidth: '14rem' }}>
<EuiCard
icon={getImage(
`${INTEGRATIONS_BASE}/repository/${i.name}/static/${i.statics.logo.path}`
http.basePath.prepend(
`${INTEGRATIONS_BASE}/repository/${i.name}/static/${i.statics.logo.path}`
)
)}
title={i.displayName ? i.displayName : i.name}
description={i.description}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ import {
} from '@elastic/eui';
import _ from 'lodash';
import React, { useEffect, useState } from 'react';
import { INTEGRATION_CATEOGRY_OPTIONS } from '../../../../common/constants/integrations';
import { IntegrationHeader } from './integration_header';
import { AvailableIntegrationsTable } from './available_integration_table';
import { AvailableIntegrationsCardView } from './available_integration_card_view';
import { INTEGRATIONS_BASE } from '../../../../common/constants/shared';
import { AvailableIntegrationOverviewPageProps } from './integration_types';
import { useToast } from '../../../../public/components/common/toast';
import { HttpStart } from '../../../../../../src/core/public';

export interface AvailableIntegrationType {
name: string;
Expand Down Expand Up @@ -55,6 +55,7 @@ export interface AvailableIntegrationsCardViewProps {
query: string;
setQuery: (input: string) => void;
renderCateogryFilters: () => React.JSX.Element;
http: HttpStart;
}

export function AvailableIntegrationOverviewPage(props: AvailableIntegrationOverviewPageProps) {
Expand All @@ -75,41 +76,27 @@ export function AvailableIntegrationOverviewPage(props: AvailableIntegrationOver
setIsPopoverOpen(false);
};

const [items, setItems] = useState(
INTEGRATION_CATEOGRY_OPTIONS.map((x) => {
return { name: x };
})
);
const [items, setItems] = useState([] as Array<{ name: string; checked: boolean }>);

function updateItem(index) {
function updateItem(index: number) {
if (!items[index]) {
return;
}

const newItems = [...items];

switch (newItems[index].checked) {
case 'on':
newItems[index].checked = undefined;
break;

default:
newItems[index].checked = 'on';
}

newItems[index].checked = !items[index].checked;
setItems(newItems);
}

const helper = items.filter((item) => item.checked === 'on').map((x) => x.name);
const helper = items.filter((item) => item.checked).map((x) => x.name);

const button = (
<EuiFilterButton
iconType="arrowDown"
onClick={onButtonClick}
isSelected={isPopoverOpen}
numFilters={items.length}
hasActiveFilters={!!items.find((item) => item.checked === 'on')}
numActiveFilters={items.filter((item) => item.checked === 'on').length}
hasActiveFilters={!!items.find((item) => item.checked)}
numActiveFilters={items.filter((item) => item.checked).length}
>
Categories
</EuiFilterButton>
Expand All @@ -126,7 +113,20 @@ export function AvailableIntegrationOverviewPage(props: AvailableIntegrationOver
}, []);

async function handleDataRequest() {
http.get(`${INTEGRATIONS_BASE}/repository`).then((exists) => setData(exists.data));
http.get(`${INTEGRATIONS_BASE}/repository`).then((exists) => {
setData(exists.data);

let newItems = exists.data.hits
.flatMap((hit: { components: Array<{ name: string }> }) => hit.components)
.map((component: { name: string }) => component.name);
newItems = [...new Set(newItems)].sort().map((newItem) => {
return {
name: newItem,
checked: false,
};
});
setItems(newItems);
});
}

async function addIntegrationRequest(name: string) {
Expand Down Expand Up @@ -163,7 +163,7 @@ export function AvailableIntegrationOverviewPage(props: AvailableIntegrationOver
<div className="ouiFilterSelect__items">
{items.map((item, index) => (
<EuiFilterSelectItem
checked={item.checked}
checked={item.checked ? 'on' : 'off'}
key={index}
onClick={() => updateItem(index)}
>
Expand Down Expand Up @@ -192,6 +192,7 @@ export function AvailableIntegrationOverviewPage(props: AvailableIntegrationOver
query,
setQuery,
renderCateogryFilters,
http,
})
: AvailableIntegrationsTable({
loading: false,
Expand Down
68 changes: 28 additions & 40 deletions public/components/integrations/components/integration.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,36 +48,28 @@ export function Integration(props: AvailableIntegrationProps) {
): Promise<{ [key: string]: { properties: any } } | null> => {
const version = payload.template.mappings._meta.version;
if (componentName !== integration.type) {
return fetch(
`/api/console/proxy?path=_component_template/ss4o_${componentName}_${version}_template&method=POST`,
{
method: 'POST',
headers: [
['osd-xsrf', 'true'],
['Content-Type', 'application/json'],
],
return http
.post('/api/console/proxy', {
body: JSON.stringify(payload),
}
)
.then((response) => response.json())
query: {
path: `_component_template/ss4o_${componentName}_${version}_template`,
method: 'POST',
},
})
.catch((err: any) => {
console.error(err);
return err;
});
} else {
payload.index_patterns = [dataSourceName];
return fetch(
`/api/console/proxy?path=_index_template/${componentName}_${version}&method=POST`,
{
method: 'POST',
headers: [
['osd-xsrf', 'true'],
['Content-Type', 'application/json'],
],
return http
.post('/api/console/proxy', {
body: JSON.stringify(payload),
}
)
.then((response) => response.json())
query: {
path: `_index_template/${componentName}_${version}`,
method: 'POST',
},
})
.catch((err: any) => {
console.error(err);
return err;
Expand All @@ -86,11 +78,7 @@ export function Integration(props: AvailableIntegrationProps) {
};

const createDataSourceMappings = async (targetDataSource: string): Promise<any> => {
const data = await fetch(
`${INTEGRATIONS_BASE}/repository/${integrationTemplateId}/schema`
).then((response) => {
return response.json();
});
const data = await http.get(`${INTEGRATIONS_BASE}/repository/${integrationTemplateId}/schema`);
let error = null;
const mappings = data.data.mappings;
mappings[integration.type].composed_of = mappings[integration.type].composed_of.map(
Expand Down Expand Up @@ -147,8 +135,8 @@ export function Integration(props: AvailableIntegrationProps) {
if (Object.keys(integration).length === 0) {
return;
}
fetch(`${INTEGRATIONS_BASE}/repository/${integration.name}/schema`)
.then((response) => response.json())
http
.get(`${INTEGRATIONS_BASE}/repository/${integration.name}/schema`)
.then((parsedResponse) => {
if (parsedResponse.statusCode && parsedResponse.statusCode !== 200) {
throw new Error('Request for schema failed: ' + parsedResponse.message);
Expand All @@ -165,8 +153,8 @@ export function Integration(props: AvailableIntegrationProps) {
if (Object.keys(integration).length === 0) {
return;
}
fetch(`${INTEGRATIONS_BASE}/repository/${integration.name}/assets`)
.then((response) => response.json())
http
.get(`${INTEGRATIONS_BASE}/repository/${integration.name}/assets`)
.then((parsedResponse) => {
if (parsedResponse.statusCode && parsedResponse.statusCode !== 200) {
throw new Error('Request for assets failed: ' + parsedResponse.message);
Expand Down Expand Up @@ -224,14 +212,14 @@ export function Integration(props: AvailableIntegrationProps) {
data.sampleData
.map((record) => `{"create": { "_index": "${dataSource}" } }\n${JSON.stringify(record)}`)
.join('\n') + '\n';
fetch(`/api/console/proxy?path=${dataSource}/_bulk&method=POST`, {
method: 'POST',
body: requestBody,
headers: [
['osd-xsrf', 'true'],
['Content-Type', 'application/json; charset=utf-8'],
],
})
http
.post('/api/console/proxy', {
body: requestBody,
query: {
path: `${dataSource}/_bulk`,
method: 'POST',
},
})
.catch((err) => {
console.error(err);
setToast('Failed to load sample data', 'danger');
Expand Down Expand Up @@ -298,7 +286,7 @@ export function Integration(props: AvailableIntegrationProps) {
<EuiSpacer />
{IntegrationDetails({ integration })}
<EuiSpacer />
{IntegrationScreenshots({ integration })}
{IntegrationScreenshots({ integration, http })}
<EuiSpacer />
<EuiTabs display="condensed">{renderTabs()}</EuiTabs>
<EuiSpacer size="s" />
Expand Down
Loading

0 comments on commit 589d6f5

Please sign in to comment.