Skip to content

Commit

Permalink
Add redux thunk fns; add cat indices API
Browse files Browse the repository at this point in the history
Signed-off-by: Tyler Ohlsen <[email protected]>
  • Loading branch information
ohltyler committed Sep 22, 2023
1 parent d3bb6bb commit bce47a8
Show file tree
Hide file tree
Showing 9 changed files with 144 additions and 14 deletions.
4 changes: 3 additions & 1 deletion common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@
export const PLUGIN_ID = 'aiFlowDashboards';

export const BASE_NODE_API_PATH = '/api/ai_flow';
export const SEARCH_PATH = `${BASE_NODE_API_PATH}/search`;
export const BASE_INDICES_NODE_API_PATH = `${BASE_NODE_API_PATH}/indices`;
export const SEARCH_INDICES_PATH = `${BASE_INDICES_NODE_API_PATH}/search`;
export const FETCH_INDICES_PATH = `${BASE_INDICES_NODE_API_PATH}/fetch`;
1 change: 1 addition & 0 deletions common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
*/

export * from './constants';
export * from './interfaces';
14 changes: 14 additions & 0 deletions common/interfaces.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

/**
* Interfaces here are primarily used for standardizing the data across
* server & client side
*/

export interface IIndex {
name: string;
health: 'green' | 'yellow' | 'red';
}
15 changes: 13 additions & 2 deletions public/route_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,19 @@
*/

import { CoreStart, HttpFetchError } from '../../../src/core/public';
import { SEARCH_PATH } from '../common';
import { FETCH_INDICES_PATH, SEARCH_INDICES_PATH } from '../common';

export interface RouteService {
searchIndex: (indexName: string, body: {}) => Promise<any | HttpFetchError>;
fetchIndices: (pattern: string) => Promise<any | HttpFetchError>;
}

export function configureRoutes(core: CoreStart): RouteService {
return {
searchIndex: async (indexName: string, body: {}) => {
try {
const response = await core.http.post<{ respString: string }>(
`${SEARCH_PATH}/${indexName}`,
`${SEARCH_INDICES_PATH}/${indexName}`,
{
body: JSON.stringify(body),
}
Expand All @@ -25,5 +26,15 @@ export function configureRoutes(core: CoreStart): RouteService {
return e as HttpFetchError;
}
},
fetchIndices: async (pattern: string) => {
try {
const response = await core.http.post<{ respString: string }>(
`${FETCH_INDICES_PATH}/${pattern}`
);
return response;
} catch (e: any) {
return e as HttpFetchError;
}
},
};
}
1 change: 1 addition & 0 deletions public/store/reducers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
*/

export * from './workspace_reducer';
export * from './opensearch_reducer';
58 changes: 58 additions & 0 deletions public/store/reducers/opensearch_reducer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
import { getRouteService } from '../../services';
import { IIndex } from '../../../common';

const initialState = {
loading: false,
errorMessage: '',
indices: {} as { [key: string]: IIndex },
};

const OPENSEARCH_PREFIX = 'opensearch';
const FETCH_INDICES_ACTION = `${OPENSEARCH_PREFIX}/fetchIndices`;

export const fetchIndices = createAsyncThunk(
FETCH_INDICES_ACTION,
async (pattern?: string) => {
// defaulting to fetch everything except system indices (starting with '.')
const patternString = pattern || '*,-.*';
const response = getRouteService().fetchIndices(patternString);
return response;
}
);

const opensearchSlice = createSlice({
name: OPENSEARCH_PREFIX,
initialState,
reducers: {
setIndices(state, action) {
state.indices = action.payload;
},
},
extraReducers: (builder) => {
builder
.addCase(fetchIndices.pending, (state, action) => {
state.loading = true;
})
.addCase(fetchIndices.fulfilled, (state, action) => {
const indicesMap = new Map<string, IIndex>();
action.payload.forEach((index: IIndex) => {
indicesMap.set(index.name, index);
});
state.indices = Object.fromEntries(indicesMap.entries());
state.loading = false;
})
.addCase(fetchIndices.rejected, (state, action) => {
state.errorMessage = action.payload as string;
state.loading = false;
});
},
});

export const opensearchReducer = opensearchSlice.reducer;
export const { setIndices } = opensearchSlice.actions;
3 changes: 2 additions & 1 deletion public/store/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@

import { configureStore } from '@reduxjs/toolkit';
import { combineReducers } from 'redux';
import { workspaceReducer } from './reducers';
import { workspaceReducer, opensearchReducer } from './reducers';

const rootReducer = combineReducers({
workspace: workspaceReducer,
opensearch: opensearchReducer,
});
export const store = configureStore({
reducer: rootReducer,
Expand Down
18 changes: 18 additions & 0 deletions server/routes/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

// OSD does not provide an interface for this response, but this is following the suggested
// implementations. To prevent typescript complaining, leaving as loosely-typed 'any'
export function generateCustomError(res: any, err: any) {
return res.customError({
statusCode: err.statusCode || 500,
body: {
message: err.message,
attributes: {
error: err.body?.error || err.message,
},
},
});
}
44 changes: 34 additions & 10 deletions server/routes/opensearch_routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ import {
IRouter,
IOpenSearchDashboardsResponse,
} from '../../../../src/core/server';
import { SEARCH_PATH } from '../../common';
import { SEARCH_INDICES_PATH, FETCH_INDICES_PATH, IIndex } from '../../common';
import { generateCustomError } from './helpers';

export function registerOpenSearchRoutes(router: IRouter): void {
router.post(
{
path: `${SEARCH_PATH}/{index_name}`,
path: `${SEARCH_INDICES_PATH}/{index_name}`,
validate: {
params: schema.object({
index_name: schema.string(),
Expand All @@ -37,15 +38,38 @@ export function registerOpenSearchRoutes(router: IRouter): void {
const response = await client.search(params);
return res.ok({ body: response });
} catch (err: any) {
return res.customError({
statusCode: err.statusCode || 500,
body: {
message: err.message,
attributes: {
error: err.body?.error || err.message,
},
},
return generateCustomError(res, err);
}
}
);
router.post(
{
path: `${FETCH_INDICES_PATH}/{pattern}`,
validate: {
params: schema.object({
pattern: schema.string(),
}),
},
},
async (context, req, res): Promise<IOpenSearchDashboardsResponse<any>> => {
const client = context.core.opensearch.client.asCurrentUser;
const { pattern } = req.params;
try {
const response = await client.cat.indices({
index: pattern,
format: 'json',
h: 'health,index',
});

// re-formatting the index results to match IIndex
const cleanedIndices = response.body.map((index) => ({
name: index.index,
health: index.health,
})) as IIndex[];

return res.ok({ body: cleanedIndices });
} catch (err: any) {
return generateCustomError(res, err);
}
}
);
Expand Down

0 comments on commit bce47a8

Please sign in to comment.