-
Notifications
You must be signed in to change notification settings - Fork 898
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Workspace]Fix error toasts in sample data page #8842
base: main
Are you sure you want to change the base?
Changes from all commits
b92b333
f199290
d76a356
bea08d1
7cb72a2
9119767
c156004
a6e4ea4
fa38231
80fbe13
f537c6f
bddcd71
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
fix: | ||
- [Workspace]Fix error toasts in sample data page ([#8842](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/8842)) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -41,11 +41,16 @@ export async function listSampleDataSets(dataSourceId) { | |
return await getServices().http.get(sampleDataUrl, { query }); | ||
} | ||
|
||
const isWorkspaceEnabled = () => { | ||
const workspaces = getServices().application.capabilities.workspaces; | ||
return !!(workspaces && workspaces.enabled); | ||
}; | ||
|
||
export async function installSampleDataSet(id, sampleDataDefaultIndex, dataSourceId) { | ||
const query = buildQuery(dataSourceId); | ||
await getServices().http.post(`${sampleDataUrl}/${id}`, { query }); | ||
|
||
if (getServices().uiSettings.isDefault('defaultIndex')) { | ||
if (!isWorkspaceEnabled() && getServices().uiSettings.isDefault('defaultIndex')) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can we add a unit test to cover this condition check? |
||
getServices().uiSettings.set('defaultIndex', sampleDataDefaultIndex); | ||
} | ||
|
||
|
@@ -59,6 +64,11 @@ export async function uninstallSampleDataSet(id, sampleDataDefaultIndex, dataSou | |
const uiSettings = getServices().uiSettings; | ||
|
||
if ( | ||
/** | ||
* Skip this logic when workspace is enabled, as the default index pattern UI setting | ||
* will be removed in the workspace UI setting wrapper. | ||
*/ | ||
!isWorkspaceEnabled() && | ||
!uiSettings.isDefault('defaultIndex') && | ||
uiSettings.get('defaultIndex') === sampleDataDefaultIndex | ||
) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
import { setServices } from '../application/opensearch_dashboards_services'; | ||
import { installSampleDataSet, uninstallSampleDataSet } from './sample_data_client'; | ||
|
||
const mockHttp = { | ||
post: jest.fn(), | ||
delete: jest.fn(), | ||
}; | ||
|
||
const mockUiSettings = { | ||
isDefault: jest.fn(), | ||
set: jest.fn(), | ||
get: jest.fn(), | ||
}; | ||
|
||
const mockApplication = { | ||
capabilities: { | ||
workspaces: { | ||
enabled: false, | ||
}, | ||
}, | ||
}; | ||
|
||
const mockIndexPatternService = { | ||
clearCache: jest.fn(), | ||
}; | ||
|
||
const mockServices = { | ||
http: mockHttp, | ||
uiSettings: mockUiSettings, | ||
application: mockApplication, | ||
indexPatternService: mockIndexPatternService, | ||
}; | ||
|
||
setServices(mockServices); | ||
|
||
describe('installSampleDataSet', () => { | ||
beforeEach(() => { | ||
jest.clearAllMocks(); | ||
mockUiSettings.isDefault.mockReturnValue(true); | ||
setServices(mockServices); | ||
}); | ||
|
||
it('should install the sample data set and set the default index', async () => { | ||
const id = 'sample-data-id'; | ||
const sampleDataDefaultIndex = 'sample-data-index'; | ||
const dataSourceId = 'data-source-id'; | ||
|
||
await installSampleDataSet(id, sampleDataDefaultIndex, dataSourceId); | ||
|
||
expect(mockHttp.post).toHaveBeenCalledWith(`/api/sample_data/${id}`, { | ||
query: expect.anything(), | ||
}); | ||
expect(mockUiSettings.set).toHaveBeenCalledWith('defaultIndex', sampleDataDefaultIndex); | ||
expect(mockIndexPatternService.clearCache).toHaveBeenCalled(); | ||
}); | ||
|
||
it('should install the sample data set and not set the default index when workspace is enabled', async () => { | ||
const id = 'sample-data-id'; | ||
const sampleDataDefaultIndex = 'sample-data-index'; | ||
const dataSourceId = 'data-source-id'; | ||
|
||
setServices({ | ||
...mockServices, | ||
application: { | ||
capabilities: { | ||
workspaces: { | ||
enabled: true, | ||
}, | ||
}, | ||
}, | ||
}); | ||
|
||
await installSampleDataSet(id, sampleDataDefaultIndex, dataSourceId); | ||
|
||
expect(mockHttp.post).toHaveBeenCalledWith(`/api/sample_data/${id}`, { | ||
query: expect.anything(), | ||
}); | ||
expect(mockUiSettings.set).not.toHaveBeenCalled(); | ||
expect(mockIndexPatternService.clearCache).toHaveBeenCalled(); | ||
}); | ||
}); | ||
|
||
describe('uninstallSampleDataSet', () => { | ||
beforeEach(() => { | ||
jest.clearAllMocks(); | ||
mockUiSettings.isDefault.mockReturnValue(false); | ||
setServices(mockServices); | ||
}); | ||
|
||
it('should uninstall the sample data set and clear the default index', async () => { | ||
const id = 'sample-data-id'; | ||
const sampleDataDefaultIndex = 'sample-data-index'; | ||
const dataSourceId = 'data-source-id'; | ||
|
||
mockUiSettings.get.mockReturnValue(sampleDataDefaultIndex); | ||
|
||
await uninstallSampleDataSet(id, sampleDataDefaultIndex, dataSourceId); | ||
|
||
expect(mockHttp.delete).toHaveBeenCalledWith(`/api/sample_data/${id}`, { | ||
query: expect.anything(), | ||
}); | ||
expect(mockUiSettings.set).toHaveBeenCalledWith('defaultIndex', null); | ||
expect(mockIndexPatternService.clearCache).toHaveBeenCalled(); | ||
}); | ||
|
||
it('should uninstall the sample data set and not clear the default index when workspace is enabled', async () => { | ||
const id = 'sample-data-id'; | ||
const sampleDataDefaultIndex = 'sample-data-index'; | ||
const dataSourceId = 'data-source-id'; | ||
|
||
setServices({ | ||
...mockServices, | ||
application: { | ||
capabilities: { | ||
workspaces: { | ||
enabled: true, | ||
}, | ||
}, | ||
}, | ||
}); | ||
|
||
await uninstallSampleDataSet(id, sampleDataDefaultIndex, dataSourceId); | ||
|
||
expect(mockHttp.delete).toHaveBeenCalledWith(`/api/sample_data/${id}`, { | ||
query: expect.anything(), | ||
}); | ||
expect(mockUiSettings.set).not.toHaveBeenCalled(); | ||
expect(mockIndexPatternService.clearCache).toHaveBeenCalled(); | ||
}); | ||
|
||
it('should uninstall the sample data set and not clear the default index when it is not the sample data index', async () => { | ||
const id = 'sample-data-id'; | ||
const sampleDataDefaultIndex = 'sample-data-index'; | ||
const dataSourceId = 'data-source-id'; | ||
|
||
mockUiSettings.isDefault.mockReturnValue(false); | ||
mockUiSettings.get.mockReturnValue('other-index'); | ||
|
||
await uninstallSampleDataSet(id, sampleDataDefaultIndex, dataSourceId); | ||
|
||
expect(mockHttp.delete).toHaveBeenCalledWith(`/api/sample_data/${id}`, { | ||
query: expect.anything(), | ||
}); | ||
expect(mockUiSettings.set).not.toHaveBeenCalled(); | ||
expect(mockIndexPatternService.clearCache).toHaveBeenCalled(); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -66,6 +66,40 @@ export function createUninstallRoute( | |
? context.dataSource.opensearch.legacy.getClient(dataSourceId).callAPI | ||
: context.core.opensearch.legacy.client.callAsCurrentUser; | ||
|
||
let savedObjectsList = getFinalSavedObjects({ | ||
dataset: sampleDataset, | ||
workspaceId, | ||
dataSourceId, | ||
}); | ||
|
||
/** | ||
* Try to delete index patterns first to avoid partial delete issues. | ||
* This is necessary because default index patterns cannot be deleted | ||
* when a workspace is enabled and the user lacks the required permissions. | ||
Comment on lines
+77
to
+78
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I might miss something here, do we have special check on index pattern when deleting? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In this PR, we will delete index patterns of sample data first when user want to uninstall sample data. So there are different cases when user try to uninstall sample data.
|
||
*/ | ||
if (workspaceId) { | ||
const indexPatternDeletePromises = savedObjectsList | ||
.filter(({ type }) => type === 'index-pattern') | ||
.map(({ type, id }) => context.core.savedObjects.client.delete(type, id)); | ||
|
||
try { | ||
await Promise.all(indexPatternDeletePromises); | ||
} catch (err) { | ||
// ignore 404s since users could have deleted some of the saved objects via the UI | ||
if (_.get(err, 'output.statusCode') !== 404) { | ||
return response.customError({ | ||
statusCode: err.status || _.get(err, 'output.statusCode'), | ||
body: { | ||
message: `Unable to delete sample dataset saved objects, error: ${err.message}`, | ||
}, | ||
}); | ||
} | ||
} | ||
|
||
// Remove index patterns from the list of saved objects to be deleted | ||
savedObjectsList = savedObjectsList.filter(({ type }) => type !== 'index-pattern'); | ||
} | ||
|
||
for (let i = 0; i < sampleDataset.dataIndices.length; i++) { | ||
const dataIndexConfig = sampleDataset.dataIndices[i]; | ||
const index = | ||
|
@@ -83,12 +117,6 @@ export function createUninstallRoute( | |
} | ||
} | ||
|
||
const savedObjectsList = getFinalSavedObjects({ | ||
dataset: sampleDataset, | ||
workspaceId, | ||
dataSourceId, | ||
}); | ||
|
||
const deletePromises = savedObjectsList.map(({ type, id }) => | ||
context.core.savedObjects.client.delete(type, id) | ||
); | ||
|
@@ -99,7 +127,7 @@ export function createUninstallRoute( | |
// ignore 404s since users could have deleted some of the saved objects via the UI | ||
if (_.get(err, 'output.statusCode') !== 404) { | ||
return response.customError({ | ||
statusCode: err.status, | ||
statusCode: err.status || _.get(err, 'output.statusCode'), | ||
body: { | ||
message: `Unable to delete sample dataset saved objects, error: ${err.message}`, | ||
}, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am thinking if it is workspaceEnabled or permissionControlEnabled.