-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update onboarding interstitial to handle default Fleet assets (#108193)
- Loading branch information
Showing
19 changed files
with
380 additions
and
19 deletions.
There are no files selected for viewing
4 changes: 4 additions & 0 deletions
4
src/plugins/home/public/application/components/__snapshots__/welcome.test.tsx.snap
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
35 changes: 35 additions & 0 deletions
35
src/plugins/home/server/routes/fetch_new_instance_status.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||
* Side Public License, v 1. | ||
*/ | ||
|
||
import { IRouter } from 'src/core/server'; | ||
import { isNewInstance } from '../services/new_instance_status'; | ||
|
||
export const registerNewInstanceStatusRoute = (router: IRouter) => { | ||
router.get( | ||
{ | ||
path: '/internal/home/new_instance_status', | ||
validate: false, | ||
}, | ||
router.handleLegacyErrors(async (context, req, res) => { | ||
const { client: soClient } = context.core.savedObjects; | ||
const { client: esClient } = context.core.elasticsearch; | ||
|
||
try { | ||
return res.ok({ | ||
body: { | ||
isNewInstance: await isNewInstance({ esClient, soClient }), | ||
}, | ||
}); | ||
} catch (e) { | ||
return res.customError({ | ||
statusCode: 500, | ||
}); | ||
} | ||
}) | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
129 changes: 129 additions & 0 deletions
129
src/plugins/home/server/services/new_instance_status.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||
* Side Public License, v 1. | ||
*/ | ||
|
||
import { isNewInstance } from './new_instance_status'; | ||
import { elasticsearchServiceMock, savedObjectsClientMock } from '../../../../core/server/mocks'; | ||
|
||
describe('isNewInstance', () => { | ||
const esClient = elasticsearchServiceMock.createScopedClusterClient(); | ||
const soClient = savedObjectsClientMock.create(); | ||
|
||
beforeEach(() => jest.resetAllMocks()); | ||
|
||
it('returns true when there are no index patterns', async () => { | ||
soClient.find.mockResolvedValue({ | ||
page: 1, | ||
per_page: 100, | ||
total: 0, | ||
saved_objects: [], | ||
}); | ||
expect(await isNewInstance({ esClient, soClient })).toEqual(true); | ||
}); | ||
|
||
it('returns false when there are any index patterns other than metrics-* or logs-*', async () => { | ||
soClient.find.mockResolvedValue({ | ||
page: 1, | ||
per_page: 100, | ||
total: 1, | ||
saved_objects: [ | ||
{ | ||
id: '1', | ||
references: [], | ||
type: 'index-pattern', | ||
score: 99, | ||
attributes: { title: 'my-pattern-*' }, | ||
}, | ||
], | ||
}); | ||
expect(await isNewInstance({ esClient, soClient })).toEqual(false); | ||
}); | ||
|
||
describe('when only metrics-* and logs-* index patterns exist', () => { | ||
beforeEach(() => { | ||
soClient.find.mockResolvedValue({ | ||
page: 1, | ||
per_page: 100, | ||
total: 2, | ||
saved_objects: [ | ||
{ | ||
id: '1', | ||
references: [], | ||
type: 'index-pattern', | ||
score: 99, | ||
attributes: { title: 'metrics-*' }, | ||
}, | ||
{ | ||
id: '2', | ||
references: [], | ||
type: 'index-pattern', | ||
score: 99, | ||
attributes: { title: 'logs-*' }, | ||
}, | ||
], | ||
}); | ||
}); | ||
|
||
it('calls /_cat/indices for the index patterns', async () => { | ||
await isNewInstance({ esClient, soClient }); | ||
expect(esClient.asCurrentUser.cat.indices).toHaveBeenCalledWith({ | ||
index: 'logs-*,metrics-*', | ||
format: 'json', | ||
}); | ||
}); | ||
|
||
it('returns true if no logs or metrics indices exist', async () => { | ||
esClient.asCurrentUser.cat.indices.mockReturnValue( | ||
elasticsearchServiceMock.createSuccessTransportRequestPromise([]) | ||
); | ||
expect(await isNewInstance({ esClient, soClient })).toEqual(true); | ||
}); | ||
|
||
it('returns true if no logs or metrics indices contain data', async () => { | ||
esClient.asCurrentUser.cat.indices.mockReturnValue( | ||
elasticsearchServiceMock.createSuccessTransportRequestPromise([ | ||
{ index: '.ds-metrics-foo', 'docs.count': '0' }, | ||
]) | ||
); | ||
expect(await isNewInstance({ esClient, soClient })).toEqual(true); | ||
}); | ||
|
||
it('returns true if only metrics-elastic_agent index contains data', async () => { | ||
esClient.asCurrentUser.cat.indices.mockReturnValue( | ||
elasticsearchServiceMock.createSuccessTransportRequestPromise([ | ||
{ index: '.ds-metrics-elastic_agent', 'docs.count': '100' }, | ||
]) | ||
); | ||
expect(await isNewInstance({ esClient, soClient })).toEqual(true); | ||
}); | ||
|
||
it('returns true if only logs-elastic_agent index contains data', async () => { | ||
esClient.asCurrentUser.cat.indices.mockReturnValue( | ||
elasticsearchServiceMock.createSuccessTransportRequestPromise([ | ||
{ index: '.ds-logs-elastic_agent', 'docs.count': '100' }, | ||
]) | ||
); | ||
expect(await isNewInstance({ esClient, soClient })).toEqual(true); | ||
}); | ||
|
||
it('returns false if any other logs or metrics indices contain data', async () => { | ||
esClient.asCurrentUser.cat.indices.mockReturnValue( | ||
elasticsearchServiceMock.createSuccessTransportRequestPromise([ | ||
{ index: '.ds-metrics-foo', 'docs.count': '100' }, | ||
]) | ||
); | ||
expect(await isNewInstance({ esClient, soClient })).toEqual(false); | ||
}); | ||
|
||
it('returns false if an authentication error is thrown', async () => { | ||
esClient.asCurrentUser.cat.indices.mockReturnValue( | ||
elasticsearchServiceMock.createErrorTransportRequestPromise({}) | ||
); | ||
expect(await isNewInstance({ esClient, soClient })).toEqual(false); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||
* Side Public License, v 1. | ||
*/ | ||
|
||
import type { IScopedClusterClient, SavedObjectsClientContract } from '../../../../core/server'; | ||
import type { IndexPatternSavedObjectAttrs } from '../../../data/common/index_patterns/index_patterns'; | ||
|
||
const LOGS_INDEX_PATTERN = 'logs-*'; | ||
const METRICS_INDEX_PATTERN = 'metrics-*'; | ||
|
||
const INDEX_PREFIXES_TO_IGNORE = [ | ||
'.ds-metrics-elastic_agent', // ignore index created by Fleet server itself | ||
'.ds-logs-elastic_agent', // ignore index created by Fleet server itself | ||
]; | ||
|
||
interface Deps { | ||
esClient: IScopedClusterClient; | ||
soClient: SavedObjectsClientContract; | ||
} | ||
|
||
export const isNewInstance = async ({ esClient, soClient }: Deps): Promise<boolean> => { | ||
const indexPatterns = await soClient.find<IndexPatternSavedObjectAttrs>({ | ||
type: 'index-pattern', | ||
fields: ['title'], | ||
search: `*`, | ||
searchFields: ['title'], | ||
perPage: 100, | ||
}); | ||
|
||
// If there are no index patterns, assume this is a new instance | ||
if (indexPatterns.total === 0) { | ||
return true; | ||
} | ||
|
||
// If there are any index patterns that are not the default metrics-* and logs-* ones created by Fleet, assume this | ||
// is not a new instance | ||
if ( | ||
indexPatterns.saved_objects.some( | ||
(ip) => | ||
ip.attributes.title !== LOGS_INDEX_PATTERN && ip.attributes.title !== METRICS_INDEX_PATTERN | ||
) | ||
) { | ||
return false; | ||
} | ||
|
||
try { | ||
const logsAndMetricsIndices = await esClient.asCurrentUser.cat.indices({ | ||
index: `${LOGS_INDEX_PATTERN},${METRICS_INDEX_PATTERN}`, | ||
format: 'json', | ||
}); | ||
|
||
const anyIndicesContainerUserData = logsAndMetricsIndices.body | ||
// Ignore some data that is shipped by default | ||
.filter(({ index }) => !INDEX_PREFIXES_TO_IGNORE.some((prefix) => index?.startsWith(prefix))) | ||
// If any other logs and metrics indices have data, return false | ||
.some((catResult) => (catResult['docs.count'] ?? '0') !== '0'); | ||
|
||
return !anyIndicesContainerUserData; | ||
} catch (e) { | ||
// If any errors are encountered return false to be safe | ||
return false; | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||
* Side Public License, v 1. | ||
*/ | ||
|
||
import expect from '@kbn/expect'; | ||
import { FtrProviderContext } from '../../ftr_provider_context'; | ||
|
||
export default function ({ getService, getPageObjects }: FtrProviderContext) { | ||
const browser = getService('browser'); | ||
const esArchiver = getService('esArchiver'); | ||
const PageObjects = getPageObjects(['common', 'home']); | ||
|
||
describe('Welcome interstitial', () => { | ||
before(async () => { | ||
// Need to navigate to page first to clear storage before test can be run | ||
await PageObjects.common.navigateToUrl('home', undefined); | ||
await browser.clearLocalStorage(); | ||
await esArchiver.emptyKibanaIndex(); | ||
}); | ||
|
||
it('is displayed on a fresh on-prem install', async () => { | ||
await PageObjects.common.navigateToUrl('home', undefined, { disableWelcomePrompt: false }); | ||
expect(await PageObjects.home.isWelcomeInterstitialDisplayed()).to.be(true); | ||
}); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.