diff --git a/public/components/integrations/components/add_integration_flyout.tsx b/public/components/integrations/components/add_integration_flyout.tsx index bfdfaa23e5..29cc8921e6 100644 --- a/public/components/integrations/components/add_integration_flyout.tsx +++ b/public/components/integrations/components/add_integration_flyout.tsx @@ -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); @@ -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) => { @@ -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 }); diff --git a/public/components/integrations/components/available_integration_card_view.tsx b/public/components/integrations/components/available_integration_card_view.tsx index ebcf6f1aa0..b3e3880d6a 100644 --- a/public/components/integrations/components/available_integration_card_view.tsx +++ b/public/components/integrations/components/available_integration_card_view.tsx @@ -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) => { @@ -72,7 +73,9 @@ export function AvailableIntegrationsCardView(props: AvailableIntegrationsCardVi void; renderCateogryFilters: () => React.JSX.Element; + http: HttpStart; } export function AvailableIntegrationOverviewPage(props: AvailableIntegrationOverviewPageProps) { @@ -190,6 +192,7 @@ export function AvailableIntegrationOverviewPage(props: AvailableIntegrationOver query, setQuery, renderCateogryFilters, + http, }) : AvailableIntegrationsTable({ loading: false, diff --git a/public/components/integrations/components/integration.tsx b/public/components/integrations/components/integration.tsx index e23e902b9f..0c37cafc03 100644 --- a/public/components/integrations/components/integration.tsx +++ b/public/components/integrations/components/integration.tsx @@ -70,27 +70,38 @@ export function Integration(props: AvailableIntegrationProps) { dataSourceName: string ): Promise<{ [key: string]: { properties: any } } | null> => { const version = payload.template.mappings._meta.version; - payload.index_patterns = [dataSourceName]; - return http - .post('/api/console/proxy', { - body: JSON.stringify(payload), - query: { - path: `_index_template/ss4o_${componentName}-${integration.name}-${version}-sample`, - method: 'POST', - }, - }) - .catch((err: any) => { - console.error(err); - return err; - }); + if (componentName !== integration.type) { + return http + .post('/api/console/proxy', { + body: JSON.stringify(payload), + query: { + path: `_component_template/ss4o_${componentName}_${version}_template`, + method: 'POST', + }, + }) + .catch((err: any) => { + console.error(err); + return err; + }); + } else { + payload.index_patterns = [dataSourceName]; + return http + .post('/api/console/proxy', { + body: JSON.stringify(payload), + query: { + path: `_index_template/${componentName}_${version}`, + method: 'POST', + }, + }) + .catch((err: any) => { + console.error(err); + return err; + }); + } }; const createDataSourceMappings = async (targetDataSource: string): Promise => { - 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( @@ -152,8 +163,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); @@ -170,8 +181,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); @@ -229,14 +240,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'); @@ -303,7 +314,7 @@ export function Integration(props: AvailableIntegrationProps) { {IntegrationDetails({ integration })} - {IntegrationScreenshots({ integration })} + {IntegrationScreenshots({ integration, http })} {renderTabs()} diff --git a/public/components/integrations/components/integration_screenshots_panel.tsx b/public/components/integrations/components/integration_screenshots_panel.tsx index 4c993a895c..d05f38ca5e 100644 --- a/public/components/integrations/components/integration_screenshots_panel.tsx +++ b/public/components/integrations/components/integration_screenshots_panel.tsx @@ -10,6 +10,7 @@ import { INTEGRATIONS_BASE } from '../../../../common/constants/shared'; export function IntegrationScreenshots(props: any) { const config = props.integration; + const http = props.http; let screenshots; if (config.statics.gallery) { screenshots = config.statics.gallery; @@ -23,7 +24,9 @@ export function IntegrationScreenshots(props: any) { return ( { - it('Should pass shallow validation for all local integrations.', async () => { - const repository: Repository = new Repository(path.join(__dirname, '../__data__/repository')); - const integrations: Integration[] = await repository.getIntegrationList(); - await Promise.all(integrations.map((i) => expect(i.check()).resolves.toBeTruthy())); + it('Should only contain valid integration directories or files.', async () => { + const directory = path.join(__dirname, '../__data__/repository'); + const folders = await fs.readdir(directory); + await Promise.all( + folders.map(async (folder) => { + const integPath = path.join(directory, folder); + if (!(await fs.lstat(integPath)).isDirectory()) { + // If it's not a directory (e.g. a README), skip it + return Promise.resolve(null); + } + // Otherwise, all directories must be integrations + const integ = new Integration(integPath); + await expect(integ.check()).resolves.toBe(true); + }) + ); }); it('Should pass deep validation for all local integrations.', async () => {