Convert to using new status, and remove legacy plugin (#75806)

* Convert to using new status, and remove legacy plugin

* PR feedback

* Fix test

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
Chris Roberson 2020-08-31 11:42:17 -04:00 committed by GitHub
parent b21071e54b
commit 54926523e8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 32 additions and 298 deletions

1
.github/CODEOWNERS vendored
View file

@ -85,7 +85,6 @@
/x-pack/plugins/ingest_manager/ @elastic/ingest-management
/x-pack/legacy/plugins/ingest_manager/ @elastic/ingest-management
/x-pack/plugins/observability/ @elastic/observability-ui
/x-pack/legacy/plugins/monitoring/ @elastic/stack-monitoring-ui
/x-pack/plugins/monitoring/ @elastic/stack-monitoring-ui
/x-pack/plugins/uptime @elastic/uptime

View file

@ -35,7 +35,7 @@
"xpack.main": "legacy/plugins/xpack_main",
"xpack.maps": ["plugins/maps", "legacy/plugins/maps"],
"xpack.ml": ["plugins/ml", "legacy/plugins/ml"],
"xpack.monitoring": ["plugins/monitoring", "legacy/plugins/monitoring"],
"xpack.monitoring": ["plugins/monitoring"],
"xpack.remoteClusters": "plugins/remote_clusters",
"xpack.painlessLab": "plugins/painless_lab",
"xpack.reporting": ["plugins/reporting"],

View file

@ -5,10 +5,9 @@
*/
import { xpackMain } from './legacy/plugins/xpack_main';
import { monitoring } from './legacy/plugins/monitoring';
import { security } from './legacy/plugins/security';
import { spaces } from './legacy/plugins/spaces';
module.exports = function (kibana) {
return [xpackMain(kibana), monitoring(kibana), spaces(kibana), security(kibana)];
return [xpackMain(kibana), spaces(kibana), security(kibana)];
};

View file

@ -1,89 +0,0 @@
## Using Monitoring
The easiest way to get to know the new Monitoring is probably by [reading the
docs](https://github.com/elastic/x-plugins/blob/master/docs/public/marvel/index.asciidoc).
Install the distribution the way a customer would is pending the first release
of Unified X-Pack plugins.
## Developing
You will need to get Elasticsearch and X-Pack plugins for ES that match the
version of the UI. The best way to do this is to run `gradle run` from a clone
of the x-plugins repository.
To set up Monitoring and automatic file syncing code changes into Kibana's plugin
directory, clone the kibana and x-plugins repos in the same directory and from
`x-plugins/kibana/monitoring`, run `yarn start`.
Once the syncing process has run at least once, start the Kibana server in
development mode. It will handle restarting the server and re-optimizing the
bundles as-needed. Go to https://localhost:5601 and click Monitoring from the App
Drawer.
## Running tests
- Run the command:
```
yarn test
```
- Debug tests
Add a `debugger` line to create a breakpoint, and then:
```
gulp sync && mocha debug --compilers js:@babel/register /pathto/kibana/plugins/monitoring/pathto/__tests__/testfile.js
```
## Multicluster Setup for Development
To run the UI with multiple clusters, the easiest way is to run 2 nodes out of
the same Elasticsearch directory, but use different start up commands for each one. One
node will be assigned to the "monitoring" cluster and the other will be for the "production"
cluster.
1. Add the Security users:
```
% ./bin/x-pack/users useradd -r remote_monitoring_agent -p notsecure remote
% ./bin/x-pack/users useradd -r monitoring_user -p notsecure monitoring_user
```
1. Start up the Monitoring cluster:
```
% ./bin/elasticsearch \
-Ehttp.port=9210 \
-Ecluster.name=monitoring \
-Epath.data=monitoring-data \
-Enode.name=monitor1node1
```
1. Start up the Production cluster:
```
% ./bin/elasticsearch \
-Expack.monitoring.exporters.id2.type=http \
-Expack.monitoring.exporters.id2.host=http://127.0.0.1:9210 \
-Expack.monitoring.exporters.id2.auth.username=remote \
-Expack.monitoring.exporters.id2.auth.password=notsecure \
-Ecluster.name=production \
-Enode.name=prod1node1 \
-Epath.data=production-data
```
1. Set the Kibana config:
```
% cat config/kibana.dev.yml
monitoring.ui.elasticsearch:
hosts: "http://localhost:9210"
username: "kibana_system"
password: "changeme"
```
1. Start another Kibana instance:
```
% yarn start
```
1. Start a Kibana instance connected to the Monitoring cluster (for running queries in Sense on Monitoring data):
```
% ./bin/kibana --config config/kibana.dev.yml --elasticsearch.hosts http://localhost:9210 --server.name monitoring-kibana --server.port 5611
```

View file

@ -1,129 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
/**
* User-configurable settings for xpack.monitoring via configuration schema
* @param {Object} Joi - HapiJS Joi module that allows for schema validation
* @return {Object} config schema
*/
export const config = (Joi: any) => {
const DEFAULT_REQUEST_HEADERS = ['authorization'];
return Joi.object({
enabled: Joi.boolean().default(true),
ui: Joi.object({
enabled: Joi.boolean().default(true),
logs: Joi.object({
index: Joi.string().default('filebeat-*'),
}).default(),
ccs: Joi.object({
enabled: Joi.boolean().default(true),
}).default(),
container: Joi.object({
elasticsearch: Joi.object({
enabled: Joi.boolean().default(false),
}).default(),
logstash: Joi.object({
enabled: Joi.boolean().default(false),
}).default(),
}).default(),
max_bucket_size: Joi.number().default(10000),
min_interval_seconds: Joi.number().default(10),
show_license_expiration: Joi.boolean().default(true),
elasticsearch: Joi.object({
customHeaders: Joi.object().default({}),
logQueries: Joi.boolean().default(false),
requestHeadersWhitelist: Joi.array().items().single().default(DEFAULT_REQUEST_HEADERS),
sniffOnStart: Joi.boolean().default(false),
sniffInterval: Joi.number().allow(false).default(false),
sniffOnConnectionFault: Joi.boolean().default(false),
hosts: Joi.array()
.items(Joi.string().uri({ scheme: ['http', 'https'] }))
.single(), // if empty, use Kibana's connection config
username: Joi.string(),
password: Joi.string(),
requestTimeout: Joi.number().default(30000),
pingTimeout: Joi.number().default(30000),
ssl: Joi.object({
verificationMode: Joi.string().valid('none', 'certificate', 'full').default('full'),
certificateAuthorities: Joi.array().single().items(Joi.string()),
certificate: Joi.string(),
key: Joi.string(),
keyPassphrase: Joi.string(),
keystore: Joi.object({
path: Joi.string(),
password: Joi.string(),
}).default(),
truststore: Joi.object({
path: Joi.string(),
password: Joi.string(),
}).default(),
alwaysPresentCertificate: Joi.boolean().default(false),
}).default(),
apiVersion: Joi.string().default('master'),
logFetchCount: Joi.number().default(10),
}).default(),
}).default(),
kibana: Joi.object({
collection: Joi.object({
enabled: Joi.boolean().default(true),
interval: Joi.number().default(10000), // op status metrics get buffered at `ops.interval` and flushed to the bulk endpoint at this interval
}).default(),
}).default(),
elasticsearch: Joi.object({
customHeaders: Joi.object().default({}),
logQueries: Joi.boolean().default(false),
requestHeadersWhitelist: Joi.array().items().single().default(DEFAULT_REQUEST_HEADERS),
sniffOnStart: Joi.boolean().default(false),
sniffInterval: Joi.number().allow(false).default(false),
sniffOnConnectionFault: Joi.boolean().default(false),
hosts: Joi.array()
.items(Joi.string().uri({ scheme: ['http', 'https'] }))
.single(), // if empty, use Kibana's connection config
username: Joi.string(),
password: Joi.string(),
requestTimeout: Joi.number().default(30000),
pingTimeout: Joi.number().default(30000),
ssl: Joi.object({
verificationMode: Joi.string().valid('none', 'certificate', 'full').default('full'),
certificateAuthorities: Joi.array().single().items(Joi.string()),
certificate: Joi.string(),
key: Joi.string(),
keyPassphrase: Joi.string(),
keystore: Joi.object({
path: Joi.string(),
password: Joi.string(),
}).default(),
truststore: Joi.object({
path: Joi.string(),
password: Joi.string(),
}).default(),
alwaysPresentCertificate: Joi.boolean().default(false),
}).default(),
apiVersion: Joi.string().default('master'),
}).default(),
cluster_alerts: Joi.object({
enabled: Joi.boolean().default(true),
email_notifications: Joi.object({
enabled: Joi.boolean().default(true),
email_address: Joi.string().email(),
}).default(),
}).default(),
licensing: Joi.object({
api_polling_frequency: Joi.number().default(30001),
}),
agent: Joi.object({
interval: Joi.string()
.regex(/[\d\.]+[yMwdhms]/)
.default('10s'),
}).default(),
tests: Joi.object({
cloud_detector: Joi.object({
enabled: Joi.boolean().default(true),
}).default(),
}).default(),
}).default();
};

View file

@ -1,37 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import Hapi from 'hapi';
import { config } from './config';
/**
* Invokes plugin modules to instantiate the Monitoring plugin for Kibana
* @param kibana {Object} Kibana plugin instance
* @return {Object} Monitoring UI Kibana plugin object
*/
const deps = ['kibana', 'elasticsearch', 'xpack_main'];
export const monitoring = (kibana: any) => {
return new kibana.Plugin({
require: deps,
id: 'monitoring',
configPrefix: 'monitoring',
init(server: Hapi.Server) {
const npMonitoring = server.newPlatform.setup.plugins.monitoring as object & {
registerLegacyAPI: (api: unknown) => void;
};
if (npMonitoring) {
const kbnServerStatus = this.kbnServer.status;
npMonitoring.registerLegacyAPI({
getServerStatus: () => {
const status = kbnServerStatus.toJSON();
return status?.overall?.state;
},
});
}
},
config,
});
};

View file

@ -5,7 +5,7 @@
*/
import { defaultsDeep, uniq, compact } from 'lodash';
import { ServiceStatusLevels } from '../../../../../src/core/server';
import {
TELEMETRY_COLLECTION_INTERVAL,
KIBANA_STATS_TYPE_MONITORING,
@ -30,7 +30,7 @@ import { sendBulkPayload, monitoringBulk } from './lib';
* @param {Object} xpackInfo server.plugins.xpack_main.info object
*/
export class BulkUploader {
constructor({ log, interval, elasticsearch, kibanaStats }) {
constructor({ log, interval, elasticsearch, statusGetter$, kibanaStats }) {
if (typeof interval !== 'number') {
throw new Error('interval number of milliseconds is required');
}
@ -52,11 +52,11 @@ export class BulkUploader {
});
this.kibanaStats = kibanaStats;
this.kibanaStatusGetter = null;
}
setKibanaStatusGetter(getter) {
this.kibanaStatusGetter = getter;
this.kibanaStatus = null;
this.kibanaStatusGetter$ = statusGetter$.subscribe((nextStatus) => {
this.kibanaStatus = nextStatus.level;
});
}
filterCollectorSet(usageCollection) {
@ -128,7 +128,7 @@ export class BulkUploader {
async _fetchAndUpload(usageCollection) {
const collectorsReady = await usageCollection.areAllCollectorsReady();
const hasUsageCollectors = usageCollection.some(usageCollection.isUsageCollector);
if (!collectorsReady || typeof this.kibanaStatusGetter !== 'function') {
if (!collectorsReady) {
this._log.debug('Skipping bulk uploading because not all collectors are ready');
if (hasUsageCollectors) {
this._lastFetchUsageTime = null;
@ -172,10 +172,23 @@ export class BulkUploader {
return await sendBulkPayload(this._cluster, this._interval, payload, this._log);
}
getConvertedKibanaStatuss() {
if (this.kibanaStatus === ServiceStatusLevels.available) {
return 'green';
}
if (this.kibanaStatus === ServiceStatusLevels.critical) {
return 'red';
}
if (this.kibanaStatus === ServiceStatusLevels.degraded) {
return 'yellow';
}
return 'unknown';
}
getKibanaStats(type) {
const stats = {
...this.kibanaStats,
status: this.kibanaStatusGetter(),
status: this.getConvertedKibanaStatuss(),
};
if (type === KIBANA_STATS_TYPE_MONITORING) {

View file

@ -5,8 +5,6 @@
*/
import { Plugin } from './plugin';
import { combineLatest } from 'rxjs';
// @ts-ignore
import { initBulkUploader } from './kibana_monitoring';
import { AlertsFactory } from './alerts';
jest.mock('rxjs', () => ({
@ -27,10 +25,6 @@ jest.mock('./license_service', () => ({
})),
}));
jest.mock('./kibana_monitoring', () => ({
initBulkUploader: jest.fn(),
}));
describe('Monitoring plugin', () => {
const initializerContext = {
logger: {
@ -71,6 +65,11 @@ describe('Monitoring plugin', () => {
createClient: jest.fn(),
},
},
status: {
overall$: {
subscribe: jest.fn(),
},
},
};
const setupPlugins = {
@ -113,19 +112,13 @@ describe('Monitoring plugin', () => {
afterEach(() => {
(setupPlugins.alerts.registerType as jest.Mock).mockReset();
(coreSetup.status.overall$.subscribe as jest.Mock).mockReset();
});
it('always create the bulk uploader', async () => {
const setKibanaStatusGetter = jest.fn();
(initBulkUploader as jest.Mock).mockImplementation(() => {
return {
setKibanaStatusGetter,
};
});
const plugin = new Plugin(initializerContext as any);
const contract = await plugin.setup(coreSetup as any, setupPlugins as any);
contract.registerLegacyAPI(null as any);
expect(setKibanaStatusGetter).toHaveBeenCalled();
await plugin.setup(coreSetup as any, setupPlugins as any);
expect(coreSetup.status.overall$.subscribe).toHaveBeenCalled();
});
it('should register all alerts', async () => {

View file

@ -46,7 +46,6 @@ import {
IBulkUploader,
PluginsSetup,
PluginsStart,
LegacyAPI,
LegacyRequest,
} from './types';
@ -158,6 +157,7 @@ export class Plugin {
elasticsearch: core.elasticsearch,
config,
log: kibanaMonitoringLog,
statusGetter$: core.status.overall$,
kibanaStats: {
uuid: this.initializerContext.env.instanceUuid,
name: serverInfo.name,
@ -221,11 +221,6 @@ export class Plugin {
}
return {
// The legacy plugin calls this to register certain legacy dependencies
// that are necessary for the plugin to properly run
registerLegacyAPI: (legacyAPI: LegacyAPI) => {
this.setupLegacy(legacyAPI);
},
// OSS stats api needs to call this in order to centralize how
// we fetch kibana specific stats
getKibanaStats: () => this.bulkUploader.getKibanaStats(),
@ -280,11 +275,6 @@ export class Plugin {
});
}
async setupLegacy(legacyAPI: LegacyAPI) {
// Set the stats getter
this.bulkUploader.setKibanaStatusGetter(() => legacyAPI.getServerStatus());
}
getLegacyShim(
config: MonitoringConfig,
legacyConfig: any,

View file

@ -33,10 +33,6 @@ export interface MonitoringElasticsearchConfig {
hosts: string[];
}
export interface LegacyAPI {
getServerStatus: () => string;
}
export interface PluginsSetup {
encryptedSavedObjects: EncryptedSavedObjectsPluginSetup;
telemetryCollectionManager?: TelemetryCollectionManagerPluginSetup;
@ -77,7 +73,6 @@ export interface LegacyShimDependencies {
}
export interface IBulkUploader {
setKibanaStatusGetter: (getter: () => string | undefined) => void;
getKibanaStats: () => any;
}