mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
* Removed license check for alerting * Fixed tests and CR feedback * Fixed test # Conflicts: # x-pack/plugins/monitoring/server/cluster_alerts/alerts_cluster_search.js # x-pack/plugins/monitoring/server/cluster_alerts/alerts_clusters_aggregation.js # x-pack/plugins/monitoring/server/cluster_alerts/verify_monitoring_license.js # x-pack/plugins/monitoring/server/deprecations.ts # x-pack/plugins/monitoring/server/lib/cluster/get_clusters_from_request.js
This commit is contained in:
parent
ab4b9d5610
commit
e4cd33d9d2
17 changed files with 10 additions and 1319 deletions
|
@ -41,17 +41,14 @@ const IsClusterSupported = ({ isSupported, children }) => {
|
|||
* completely
|
||||
*/
|
||||
const IsAlertsSupported = (props) => {
|
||||
const { alertsMeta = { enabled: true }, clusterMeta = { enabled: true } } = props.cluster.alerts;
|
||||
if (alertsMeta.enabled && clusterMeta.enabled) {
|
||||
const { alertsMeta = { enabled: true } } = props.cluster.alerts;
|
||||
if (alertsMeta.enabled) {
|
||||
return <span>{props.children}</span>;
|
||||
}
|
||||
|
||||
const message =
|
||||
alertsMeta.message ||
|
||||
clusterMeta.message ||
|
||||
i18n.translate('xpack.monitoring.cluster.listing.unknownHealthMessage', {
|
||||
defaultMessage: 'Unknown',
|
||||
});
|
||||
const message = i18n.translate('xpack.monitoring.cluster.listing.unknownHealthMessage', {
|
||||
defaultMessage: 'Unknown',
|
||||
});
|
||||
|
||||
return (
|
||||
<EuiToolTip content={message} position="bottom">
|
||||
|
|
|
@ -1,34 +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
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import sinon from 'sinon';
|
||||
|
||||
export function createStubs(mockQueryResult, featureStub) {
|
||||
const callWithRequestStub = sinon.stub().returns(Promise.resolve(mockQueryResult));
|
||||
const getClusterStub = sinon.stub().returns({ callWithRequest: callWithRequestStub });
|
||||
const configStub = sinon.stub().returns({
|
||||
get: sinon.stub().withArgs('xpack.monitoring.cluster_alerts.enabled').returns(true),
|
||||
});
|
||||
return {
|
||||
callWithRequestStub,
|
||||
mockReq: {
|
||||
server: {
|
||||
config: configStub,
|
||||
plugins: {
|
||||
monitoring: {
|
||||
info: {
|
||||
feature: featureStub,
|
||||
},
|
||||
},
|
||||
elasticsearch: {
|
||||
getCluster: getClusterStub,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
|
@ -1,227 +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
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { get } from 'lodash';
|
||||
import moment from 'moment';
|
||||
import { verifyMonitoringLicense } from './verify_monitoring_license';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
/**
|
||||
* Retrieve any statically defined cluster alerts (not indexed) for the {@code cluster}.
|
||||
*
|
||||
* In the future, if we add other static cluster alerts, then we should probably just return an array.
|
||||
* It may also make sense to put this into its own file in the future.
|
||||
*
|
||||
* @param {Object} cluster The cluster object containing the cluster's license.
|
||||
* @return {Object} The alert to use for the cluster. {@code null} if none.
|
||||
*/
|
||||
export function staticAlertForCluster(cluster) {
|
||||
const clusterNeedsTLSEnabled = get(cluster, 'license.cluster_needs_tls', false);
|
||||
|
||||
if (clusterNeedsTLSEnabled) {
|
||||
const versionParts = get(cluster, 'version', '').split('.');
|
||||
const version = versionParts.length > 1 ? `${versionParts[0]}.${versionParts[1]}` : 'current';
|
||||
|
||||
return {
|
||||
metadata: {
|
||||
severity: 0,
|
||||
cluster_uuid: cluster.cluster_uuid,
|
||||
link: `https://www.elastic.co/guide/en/x-pack/${version}/ssl-tls.html`,
|
||||
},
|
||||
update_timestamp: cluster.timestamp,
|
||||
timestamp: get(cluster, 'license.issue_date', cluster.timestamp),
|
||||
prefix: i18n.translate('xpack.monitoring.clusterAlerts.clusterNeedsTSLEnabledDescription', {
|
||||
defaultMessage:
|
||||
'Configuring TLS will be required to apply a Gold or Platinum license when security is enabled.',
|
||||
}),
|
||||
message: i18n.translate('xpack.monitoring.clusterAlerts.seeDocumentationDescription', {
|
||||
defaultMessage: 'See documentation for details.',
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append the static alert(s) for this {@code cluster}, limiting the response to {@code size} {@code alerts}.
|
||||
*
|
||||
* @param {Object} cluster The cluster object containing the cluster's license.
|
||||
* @param {Array} alerts The existing cluster alerts.
|
||||
* @param {Number} size The maximum size.
|
||||
* @return {Array} The alerts array (modified or not).
|
||||
*/
|
||||
export function appendStaticAlerts(cluster, alerts, size) {
|
||||
const staticAlert = staticAlertForCluster(cluster);
|
||||
|
||||
if (staticAlert) {
|
||||
// we can put it over any resolved alert, or anything with a lower severity (which is currently none)
|
||||
// the alerts array is pre-sorted from highest severity to lowest; unresolved alerts are at the bottom
|
||||
const alertIndex = alerts.findIndex(
|
||||
(alert) => alert.resolved_timestamp || alert.metadata.severity < staticAlert.metadata.severity
|
||||
);
|
||||
|
||||
if (alertIndex !== -1) {
|
||||
// we can put it in the place of this alert
|
||||
alerts.splice(alertIndex, 0, staticAlert);
|
||||
} else {
|
||||
alerts.push(staticAlert);
|
||||
}
|
||||
|
||||
// chop off the last item if necessary (when size is < alerts.length)
|
||||
return alerts.slice(0, size);
|
||||
}
|
||||
|
||||
return alerts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a filter that should be used when no time range is supplied and thus only un-resolved cluster alerts should
|
||||
* be returned.
|
||||
*
|
||||
* @return {Object} Query to restrict to un-resolved cluster alerts.
|
||||
*/
|
||||
export function createFilterForUnresolvedAlerts() {
|
||||
return {
|
||||
bool: {
|
||||
must_not: {
|
||||
exists: {
|
||||
field: 'resolved_timestamp',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a filter that should be used when {@code options} has start or end times.
|
||||
*
|
||||
* This enables us to search for cluster alerts that have been resolved within the given time frame, while also
|
||||
* grabbing any un-resolved cluster alerts.
|
||||
*
|
||||
* @param {Object} options The options for the cluster search.
|
||||
* @return {Object} Query to restrict to un-resolved cluster alerts or cluster alerts resolved within the time range.
|
||||
*/
|
||||
export function createFilterForTime(options) {
|
||||
const timeFilter = {};
|
||||
|
||||
if (options.start) {
|
||||
timeFilter.gte = moment.utc(options.start).valueOf();
|
||||
}
|
||||
|
||||
if (options.end) {
|
||||
timeFilter.lte = moment.utc(options.end).valueOf();
|
||||
}
|
||||
|
||||
return {
|
||||
bool: {
|
||||
should: [
|
||||
{
|
||||
range: {
|
||||
resolved_timestamp: {
|
||||
format: 'epoch_millis',
|
||||
...timeFilter,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
bool: {
|
||||
must_not: {
|
||||
exists: {
|
||||
field: 'resolved_timestamp',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} req Request object from the API route
|
||||
* @param {String} cluster The cluster being checked
|
||||
*/
|
||||
export function alertsClusterSearch(req, alertsIndex, cluster, checkLicense, options = {}) {
|
||||
const verification = verifyMonitoringLicense(req.server);
|
||||
|
||||
if (!verification.enabled) {
|
||||
return Promise.resolve({ message: verification.message });
|
||||
}
|
||||
|
||||
const license = get(cluster, 'license', {});
|
||||
const prodLicenseInfo = checkLicense(license.type, license.status === 'active', 'production');
|
||||
|
||||
if (prodLicenseInfo.clusterAlerts.enabled) {
|
||||
const config = req.server.config();
|
||||
const size = options.size || config.get('monitoring.ui.max_bucket_size');
|
||||
|
||||
const params = {
|
||||
index: alertsIndex,
|
||||
ignoreUnavailable: true,
|
||||
filterPath: 'hits.hits._source',
|
||||
body: {
|
||||
size,
|
||||
query: {
|
||||
bool: {
|
||||
must: [
|
||||
{
|
||||
// This will cause anything un-resolved to be sorted above anything that is resolved
|
||||
// From there, those items are sorted by their severity, then by their timestamp (age)
|
||||
function_score: {
|
||||
boost_mode: 'max',
|
||||
functions: [
|
||||
{
|
||||
filter: {
|
||||
bool: {
|
||||
must_not: [
|
||||
{
|
||||
exists: {
|
||||
field: 'resolved_timestamp',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
weight: 2,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
filter: [
|
||||
{
|
||||
term: { 'metadata.cluster_uuid': cluster.cluster_uuid },
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
sort: [
|
||||
'_score',
|
||||
{ 'metadata.severity': { order: 'desc' } },
|
||||
{ timestamp: { order: 'asc' } },
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
if (options.start || options.end) {
|
||||
params.body.query.bool.filter.push(createFilterForTime(options));
|
||||
} else {
|
||||
params.body.query.bool.filter.push(createFilterForUnresolvedAlerts());
|
||||
}
|
||||
|
||||
const { callWithRequest } = req.server.plugins.elasticsearch.getCluster('monitoring');
|
||||
return callWithRequest(req, 'search', params).then((result) => {
|
||||
const hits = get(result, 'hits.hits', []);
|
||||
const alerts = hits.map((alert) => alert._source);
|
||||
|
||||
return appendStaticAlerts(cluster, alerts, size);
|
||||
});
|
||||
}
|
||||
|
||||
return Promise.resolve({ message: prodLicenseInfo.message });
|
||||
}
|
|
@ -1,194 +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
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import expect from '@kbn/expect';
|
||||
import sinon from 'sinon';
|
||||
import { createStubs } from './__fixtures__/create_stubs';
|
||||
import { alertsClusterSearch } from './alerts_cluster_search';
|
||||
|
||||
const mockAlerts = [
|
||||
{
|
||||
metadata: {
|
||||
severity: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
metadata: {
|
||||
severity: -1,
|
||||
},
|
||||
},
|
||||
{
|
||||
metadata: {
|
||||
severity: 2000,
|
||||
},
|
||||
resolved_timestamp: 'now',
|
||||
},
|
||||
];
|
||||
|
||||
const mockQueryResult = {
|
||||
hits: {
|
||||
hits: [
|
||||
{
|
||||
_source: mockAlerts[0],
|
||||
},
|
||||
{
|
||||
_source: mockAlerts[1],
|
||||
},
|
||||
{
|
||||
_source: mockAlerts[2],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
// TODO: tests were not running and are not up to date.
|
||||
describe.skip('Alerts Cluster Search', () => {
|
||||
describe('License checks pass', () => {
|
||||
const featureStub = sinon.stub().returns({
|
||||
getLicenseCheckResults: () => ({ clusterAlerts: { enabled: true } }),
|
||||
});
|
||||
const checkLicense = () => ({ clusterAlerts: { enabled: true } });
|
||||
|
||||
it('max hit count option', () => {
|
||||
const { mockReq, callWithRequestStub } = createStubs(mockQueryResult, featureStub);
|
||||
return alertsClusterSearch(
|
||||
mockReq,
|
||||
'.monitoring-alerts',
|
||||
{ cluster_uuid: 'cluster-1234' },
|
||||
checkLicense
|
||||
).then((alerts) => {
|
||||
expect(alerts).to.eql(mockAlerts);
|
||||
expect(callWithRequestStub.getCall(0).args[2].body.size).to.be.undefined;
|
||||
});
|
||||
});
|
||||
|
||||
it('set hit count option', () => {
|
||||
const { mockReq, callWithRequestStub } = createStubs(mockQueryResult, featureStub);
|
||||
return alertsClusterSearch(
|
||||
mockReq,
|
||||
'.monitoring-alerts',
|
||||
{ cluster_uuid: 'cluster-1234' },
|
||||
checkLicense,
|
||||
{ size: 3 }
|
||||
).then((alerts) => {
|
||||
expect(alerts).to.eql(mockAlerts);
|
||||
expect(callWithRequestStub.getCall(0).args[2].body.size).to.be(3);
|
||||
});
|
||||
});
|
||||
|
||||
it('should report static info-level alert in the right location', () => {
|
||||
const { mockReq, callWithRequestStub } = createStubs(mockQueryResult, featureStub);
|
||||
const cluster = {
|
||||
cluster_uuid: 'cluster-1234',
|
||||
timestamp: 'fake-timestamp',
|
||||
version: '6.1.0-throwmeaway2',
|
||||
license: {
|
||||
cluster_needs_tls: true,
|
||||
issue_date: 'fake-issue_date',
|
||||
},
|
||||
};
|
||||
return alertsClusterSearch(mockReq, '.monitoring-alerts', cluster, checkLicense, {
|
||||
size: 3,
|
||||
}).then((alerts) => {
|
||||
expect(alerts).to.have.length(3);
|
||||
expect(alerts[0]).to.eql(mockAlerts[0]);
|
||||
expect(alerts[1]).to.eql({
|
||||
metadata: {
|
||||
severity: 0,
|
||||
|
||||
cluster_uuid: cluster.cluster_uuid,
|
||||
link: 'https://www.elastic.co/guide/en/x-pack/6.1/ssl-tls.html',
|
||||
},
|
||||
update_timestamp: cluster.timestamp,
|
||||
timestamp: cluster.license.issue_date,
|
||||
prefix:
|
||||
'Configuring TLS will be required to apply a Gold or Platinum license when security is enabled.',
|
||||
message: 'See documentation for details.',
|
||||
});
|
||||
expect(alerts[2]).to.eql(mockAlerts[1]);
|
||||
expect(callWithRequestStub.getCall(0).args[2].body.size).to.be(3);
|
||||
});
|
||||
});
|
||||
|
||||
it('should report static info-level alert at the end if necessary', () => {
|
||||
const { mockReq, callWithRequestStub } = createStubs({ hits: { hits: [] } }, featureStub);
|
||||
const cluster = {
|
||||
cluster_uuid: 'cluster-1234',
|
||||
timestamp: 'fake-timestamp',
|
||||
version: '6.1.0-throwmeaway2',
|
||||
license: {
|
||||
cluster_needs_tls: true,
|
||||
issue_date: 'fake-issue_date',
|
||||
},
|
||||
};
|
||||
return alertsClusterSearch(mockReq, '.monitoring-alerts', cluster, checkLicense, {
|
||||
size: 3,
|
||||
}).then((alerts) => {
|
||||
expect(alerts).to.have.length(1);
|
||||
expect(alerts[0]).to.eql({
|
||||
metadata: {
|
||||
severity: 0,
|
||||
cluster_uuid: cluster.cluster_uuid,
|
||||
link: 'https://www.elastic.co/guide/en/x-pack/6.1/ssl-tls.html',
|
||||
},
|
||||
update_timestamp: cluster.timestamp,
|
||||
timestamp: cluster.license.issue_date,
|
||||
prefix:
|
||||
'Configuring TLS will be required to apply a Gold or Platinum license when security is enabled.',
|
||||
message: 'See documentation for details.',
|
||||
});
|
||||
expect(callWithRequestStub.getCall(0).args[2].body.size).to.be(3);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('License checks fail', () => {
|
||||
it('monitoring cluster license checks fail', () => {
|
||||
const featureStub = sinon.stub().returns({
|
||||
getLicenseCheckResults: () => ({
|
||||
message: 'monitoring cluster license check fail',
|
||||
clusterAlerts: { enabled: false },
|
||||
}),
|
||||
});
|
||||
const checkLicense = sinon.stub();
|
||||
const { mockReq, callWithRequestStub } = createStubs({}, featureStub);
|
||||
return alertsClusterSearch(
|
||||
mockReq,
|
||||
'.monitoring-alerts',
|
||||
{ cluster_uuid: 'cluster-1234' },
|
||||
checkLicense
|
||||
).then((alerts) => {
|
||||
const result = { message: 'monitoring cluster license check fail' };
|
||||
expect(alerts).to.eql(result);
|
||||
expect(checkLicense.called).to.be(false);
|
||||
expect(callWithRequestStub.called).to.be(false);
|
||||
});
|
||||
});
|
||||
|
||||
it('production cluster license checks fail', () => {
|
||||
// monitoring cluster passes
|
||||
const featureStub = sinon.stub().returns({
|
||||
getLicenseCheckResults: () => ({ clusterAlerts: { enabled: true } }),
|
||||
});
|
||||
const checkLicense = sinon
|
||||
.stub()
|
||||
.returns({ clusterAlerts: { enabled: false }, message: 'prod goes boom' });
|
||||
const { mockReq, callWithRequestStub } = createStubs({}, featureStub);
|
||||
return alertsClusterSearch(
|
||||
mockReq,
|
||||
'.monitoring-alerts',
|
||||
{ cluster_uuid: 'cluster-1234' },
|
||||
checkLicense
|
||||
).then((alerts) => {
|
||||
const result = { message: 'prod goes boom' };
|
||||
expect(alerts).to.eql(result);
|
||||
expect(checkLicense.calledOnce).to.be(true);
|
||||
expect(callWithRequestStub.called).to.be(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,127 +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
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { get, find } from 'lodash';
|
||||
import { verifyMonitoringLicense } from './verify_monitoring_license';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
export function alertsClustersAggregation(req, alertsIndex, clusters, checkLicense) {
|
||||
const verification = verifyMonitoringLicense(req.server);
|
||||
|
||||
if (!verification.enabled) {
|
||||
// return metadata detailing that alerts is disabled because of the monitoring cluster license
|
||||
return Promise.resolve({ alertsMeta: verification });
|
||||
}
|
||||
|
||||
const params = {
|
||||
index: alertsIndex,
|
||||
ignoreUnavailable: true,
|
||||
filterPath: 'aggregations',
|
||||
body: {
|
||||
size: 0,
|
||||
query: {
|
||||
bool: {
|
||||
must_not: [
|
||||
{
|
||||
exists: { field: 'resolved_timestamp' },
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
aggs: {
|
||||
group_by_cluster: {
|
||||
terms: {
|
||||
field: 'metadata.cluster_uuid',
|
||||
size: 10,
|
||||
},
|
||||
aggs: {
|
||||
group_by_severity: {
|
||||
range: {
|
||||
field: 'metadata.severity',
|
||||
ranges: [
|
||||
{
|
||||
key: 'low',
|
||||
to: 1000,
|
||||
},
|
||||
{
|
||||
key: 'medium',
|
||||
from: 1000,
|
||||
to: 2000,
|
||||
},
|
||||
{
|
||||
key: 'high',
|
||||
from: 2000,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const { callWithRequest } = req.server.plugins.elasticsearch.getCluster('monitoring');
|
||||
return callWithRequest(req, 'search', params).then((result) => {
|
||||
const buckets = get(result.aggregations, 'group_by_cluster.buckets');
|
||||
const meta = { alertsMeta: { enabled: true } };
|
||||
|
||||
return clusters.reduce((reClusters, cluster) => {
|
||||
let alerts;
|
||||
|
||||
const license = cluster.license || {};
|
||||
// check the license type of the production cluster for alerts feature support
|
||||
const prodLicenseInfo = checkLicense(license.type, license.status === 'active', 'production');
|
||||
if (prodLicenseInfo.clusterAlerts.enabled) {
|
||||
const clusterNeedsTLS = get(license, 'cluster_needs_tls', false);
|
||||
const staticAlertCount = clusterNeedsTLS ? 1 : 0;
|
||||
const bucket = find(buckets, { key: cluster.cluster_uuid });
|
||||
const bucketDocCount = get(bucket, 'doc_count', 0);
|
||||
let severities = {};
|
||||
|
||||
if (bucket || staticAlertCount > 0) {
|
||||
if (bucketDocCount > 0 || staticAlertCount > 0) {
|
||||
const groupBySeverityBuckets = get(bucket, 'group_by_severity.buckets', []);
|
||||
const lowGroup = find(groupBySeverityBuckets, { key: 'low' }) || {};
|
||||
const mediumGroup = find(groupBySeverityBuckets, { key: 'medium' }) || {};
|
||||
const highGroup = find(groupBySeverityBuckets, { key: 'high' }) || {};
|
||||
severities = {
|
||||
low: (lowGroup.doc_count || 0) + staticAlertCount,
|
||||
medium: mediumGroup.doc_count || 0,
|
||||
high: highGroup.doc_count || 0,
|
||||
};
|
||||
}
|
||||
|
||||
alerts = {
|
||||
count: bucketDocCount + staticAlertCount,
|
||||
...severities,
|
||||
};
|
||||
}
|
||||
} else {
|
||||
// add metadata to the cluster's alerts object detailing that alerts are disabled because of the prod cluster license
|
||||
alerts = {
|
||||
clusterMeta: {
|
||||
enabled: false,
|
||||
message: i18n.translate(
|
||||
'xpack.monitoring.clusterAlerts.unsupportedClusterAlertsDescription',
|
||||
{
|
||||
defaultMessage:
|
||||
'Cluster [{clusterName}] license type [{licenseType}] does not support Cluster Alerts',
|
||||
values: {
|
||||
clusterName: cluster.cluster_name,
|
||||
licenseType: `${license.type}`,
|
||||
},
|
||||
}
|
||||
),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
return Object.assign(reClusters, { [cluster.cluster_uuid]: alerts });
|
||||
}, meta);
|
||||
});
|
||||
}
|
|
@ -1,235 +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
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import expect from '@kbn/expect';
|
||||
import sinon from 'sinon';
|
||||
import { merge } from 'lodash';
|
||||
import { createStubs } from './__fixtures__/create_stubs';
|
||||
import { alertsClustersAggregation } from './alerts_clusters_aggregation';
|
||||
|
||||
const clusters = [
|
||||
{
|
||||
cluster_uuid: 'cluster-abc0',
|
||||
cluster_name: 'cluster-abc0-name',
|
||||
license: { type: 'test_license' },
|
||||
},
|
||||
{
|
||||
cluster_uuid: 'cluster-abc1',
|
||||
cluster_name: 'cluster-abc1-name',
|
||||
license: { type: 'test_license' },
|
||||
},
|
||||
{
|
||||
cluster_uuid: 'cluster-abc2',
|
||||
cluster_name: 'cluster-abc2-name',
|
||||
license: { type: 'test_license' },
|
||||
},
|
||||
{
|
||||
cluster_uuid: 'cluster-abc3',
|
||||
cluster_name: 'cluster-abc3-name',
|
||||
license: { type: 'test_license' },
|
||||
},
|
||||
{ cluster_uuid: 'cluster-no-license', cluster_name: 'cluster-no-license-name' },
|
||||
{ cluster_uuid: 'cluster-invalid', cluster_name: 'cluster-invalid-name', license: {} },
|
||||
];
|
||||
const mockQueryResult = {
|
||||
aggregations: {
|
||||
group_by_cluster: {
|
||||
buckets: [
|
||||
{
|
||||
key: 'cluster-abc1',
|
||||
doc_count: 1,
|
||||
group_by_severity: {
|
||||
buckets: [{ key: 'low', doc_count: 1 }],
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'cluster-abc2',
|
||||
doc_count: 2,
|
||||
group_by_severity: {
|
||||
buckets: [{ key: 'medium', doc_count: 2 }],
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'cluster-abc3',
|
||||
doc_count: 3,
|
||||
group_by_severity: {
|
||||
buckets: [{ key: 'high', doc_count: 3 }],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// TODO: tests were not running and are not up to date.
|
||||
describe.skip('Alerts Clusters Aggregation', () => {
|
||||
describe('with alerts enabled', () => {
|
||||
const featureStub = sinon.stub().returns({
|
||||
getLicenseCheckResults: () => ({ clusterAlerts: { enabled: true } }),
|
||||
});
|
||||
const checkLicense = () => ({ clusterAlerts: { enabled: true } });
|
||||
|
||||
it('aggregates alert count summary by cluster', () => {
|
||||
const { mockReq } = createStubs(mockQueryResult, featureStub);
|
||||
return alertsClustersAggregation(mockReq, '.monitoring-alerts', clusters, checkLicense).then(
|
||||
(result) => {
|
||||
expect(result).to.eql({
|
||||
alertsMeta: { enabled: true },
|
||||
'cluster-abc0': undefined,
|
||||
'cluster-abc1': {
|
||||
count: 1,
|
||||
high: 0,
|
||||
low: 1,
|
||||
medium: 0,
|
||||
},
|
||||
'cluster-abc2': {
|
||||
count: 2,
|
||||
high: 0,
|
||||
low: 0,
|
||||
medium: 2,
|
||||
},
|
||||
'cluster-abc3': {
|
||||
count: 3,
|
||||
high: 3,
|
||||
low: 0,
|
||||
medium: 0,
|
||||
},
|
||||
'cluster-no-license': undefined,
|
||||
'cluster-invalid': undefined,
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('aggregates alert count summary by cluster include static alert', () => {
|
||||
const { mockReq } = createStubs(mockQueryResult, featureStub);
|
||||
const clusterLicenseNeedsTLS = { license: { cluster_needs_tls: true } };
|
||||
const newClusters = Array.from(clusters);
|
||||
|
||||
newClusters[0] = merge({}, clusters[0], clusterLicenseNeedsTLS);
|
||||
newClusters[1] = merge({}, clusters[1], clusterLicenseNeedsTLS);
|
||||
|
||||
return alertsClustersAggregation(
|
||||
mockReq,
|
||||
'.monitoring-alerts',
|
||||
newClusters,
|
||||
checkLicense
|
||||
).then((result) => {
|
||||
expect(result).to.eql({
|
||||
alertsMeta: { enabled: true },
|
||||
'cluster-abc0': {
|
||||
count: 1,
|
||||
high: 0,
|
||||
medium: 0,
|
||||
low: 1,
|
||||
},
|
||||
'cluster-abc1': {
|
||||
count: 2,
|
||||
high: 0,
|
||||
low: 2,
|
||||
medium: 0,
|
||||
},
|
||||
'cluster-abc2': {
|
||||
count: 2,
|
||||
high: 0,
|
||||
low: 0,
|
||||
medium: 2,
|
||||
},
|
||||
'cluster-abc3': {
|
||||
count: 3,
|
||||
high: 3,
|
||||
low: 0,
|
||||
medium: 0,
|
||||
},
|
||||
'cluster-no-license': undefined,
|
||||
'cluster-invalid': undefined,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('with alerts disabled due to license', () => {
|
||||
it('returns the input set if disabled because monitoring cluster checks', () => {
|
||||
// monitoring clusters' license check to fail
|
||||
const featureStub = sinon.stub().returns({
|
||||
getLicenseCheckResults: () => ({
|
||||
clusterAlerts: { enabled: false },
|
||||
message: 'monitoring cluster license is fail',
|
||||
}),
|
||||
});
|
||||
// prod clusters' license check to pass
|
||||
const checkLicense = () => ({ clusterAlerts: { enabled: true } });
|
||||
const { mockReq } = createStubs(mockQueryResult, featureStub);
|
||||
|
||||
return alertsClustersAggregation(mockReq, '.monitoring-alerts', clusters, checkLicense).then(
|
||||
(result) => {
|
||||
expect(result).to.eql({
|
||||
alertsMeta: { enabled: false, message: 'monitoring cluster license is fail' },
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('returns the input set if disabled because production cluster checks', () => {
|
||||
// monitoring clusters' license check to pass
|
||||
const featureStub = sinon.stub().returns({
|
||||
getLicenseCheckResults: () => ({ clusterAlerts: { enabled: true } }),
|
||||
});
|
||||
// prod clusters license check to fail
|
||||
const checkLicense = () => ({ clusterAlerts: { enabled: false } });
|
||||
const { mockReq } = createStubs(mockQueryResult, featureStub);
|
||||
|
||||
return alertsClustersAggregation(mockReq, '.monitoring-alerts', clusters, checkLicense).then(
|
||||
(result) => {
|
||||
expect(result).to.eql({
|
||||
alertsMeta: { enabled: true },
|
||||
'cluster-abc0': {
|
||||
clusterMeta: {
|
||||
enabled: false,
|
||||
message:
|
||||
'Cluster [cluster-abc0-name] license type [test_license] does not support Cluster Alerts',
|
||||
},
|
||||
},
|
||||
'cluster-abc1': {
|
||||
clusterMeta: {
|
||||
enabled: false,
|
||||
message:
|
||||
'Cluster [cluster-abc1-name] license type [test_license] does not support Cluster Alerts',
|
||||
},
|
||||
},
|
||||
'cluster-abc2': {
|
||||
clusterMeta: {
|
||||
enabled: false,
|
||||
message:
|
||||
'Cluster [cluster-abc2-name] license type [test_license] does not support Cluster Alerts',
|
||||
},
|
||||
},
|
||||
'cluster-abc3': {
|
||||
clusterMeta: {
|
||||
enabled: false,
|
||||
message:
|
||||
'Cluster [cluster-abc3-name] license type [test_license] does not support Cluster Alerts',
|
||||
},
|
||||
},
|
||||
'cluster-no-license': {
|
||||
clusterMeta: {
|
||||
enabled: false,
|
||||
message: `Cluster [cluster-no-license-name] license type [undefined] does not support Cluster Alerts`,
|
||||
},
|
||||
},
|
||||
'cluster-invalid': {
|
||||
clusterMeta: {
|
||||
enabled: false,
|
||||
message: `Cluster [cluster-invalid-name] license type [undefined] does not support Cluster Alerts`,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,111 +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
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { includes } from 'lodash';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
/**
|
||||
* Function to do the work of checking license for cluster alerts feature support
|
||||
* Can be used to power XpackInfo license check results as well as checking license of monitored clusters
|
||||
*
|
||||
* @param {String} type License type if a valid license. {@code null} if license was deleted.
|
||||
* @param {Boolean} active Indicating that the overall license is active
|
||||
* @param {String} clusterSource 'monitoring' or 'production'
|
||||
* @param {Boolean} watcher {@code true} if Watcher is provided (or if its availability should not be checked)
|
||||
*/
|
||||
export function checkLicense(type, active, clusterSource, watcher = true) {
|
||||
// return object, set up with safe defaults
|
||||
const licenseInfo = {
|
||||
clusterAlerts: { enabled: false },
|
||||
};
|
||||
|
||||
// Disabled because there is no license
|
||||
if (!type) {
|
||||
return Object.assign(licenseInfo, {
|
||||
message: i18n.translate(
|
||||
'xpack.monitoring.clusterAlerts.checkLicense.licenseNotDeterminedDescription',
|
||||
{
|
||||
defaultMessage: `Cluster Alerts are not displayed because the [{clusterSource}] cluster's license could not be determined.`,
|
||||
values: {
|
||||
clusterSource,
|
||||
},
|
||||
}
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
// Disabled because the license type is not valid (basic)
|
||||
if (!includes(['trial', 'standard', 'gold', 'platinum', 'enterprise'], type)) {
|
||||
return Object.assign(licenseInfo, {
|
||||
message: i18n.translate(
|
||||
'xpack.monitoring.clusterAlerts.checkLicense.licenseIsBasicDescription',
|
||||
{
|
||||
defaultMessage: `Cluster Alerts are not displayed if Watcher is disabled or the [{clusterSource}] cluster's current license is Basic.`,
|
||||
values: {
|
||||
clusterSource,
|
||||
},
|
||||
}
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
// Disabled because the license is inactive
|
||||
if (!active) {
|
||||
return Object.assign(licenseInfo, {
|
||||
message: i18n.translate(
|
||||
'xpack.monitoring.clusterAlerts.checkLicense.licenseNotActiveDescription',
|
||||
{
|
||||
defaultMessage: `Cluster Alerts are not displayed because the [{clusterSource}] cluster's current license [{type}] is not active.`,
|
||||
values: {
|
||||
clusterSource,
|
||||
type,
|
||||
},
|
||||
}
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
// Disabled because Watcher is not enabled (it may or may not be available)
|
||||
if (!watcher) {
|
||||
return Object.assign(licenseInfo, {
|
||||
message: i18n.translate(
|
||||
'xpack.monitoring.clusterAlerts.checkLicense.watcherIsDisabledDescription',
|
||||
{
|
||||
defaultMessage: 'Cluster Alerts are not enabled because Watcher is disabled.',
|
||||
}
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
return Object.assign(licenseInfo, { clusterAlerts: { enabled: true } });
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to "generate" license check results for {@code xpackInfo}.
|
||||
*
|
||||
* @param {Object} xpackInfo license information for the _Monitoring_ cluster
|
||||
* @param {Function} _checkLicense Method exposed for easier unit testing
|
||||
* @returns {Object} Response from {@code checker}
|
||||
*/
|
||||
export function checkLicenseGenerator(xpackInfo, _checkLicense = checkLicense) {
|
||||
let type;
|
||||
let active = false;
|
||||
let watcher = false;
|
||||
|
||||
if (xpackInfo && xpackInfo.license) {
|
||||
const watcherFeature = xpackInfo.feature('watcher');
|
||||
|
||||
if (watcherFeature) {
|
||||
watcher = watcherFeature.isEnabled();
|
||||
}
|
||||
|
||||
type = xpackInfo.license.getType();
|
||||
active = xpackInfo.license.isActive();
|
||||
}
|
||||
|
||||
return _checkLicense(type, active, 'monitoring', watcher);
|
||||
}
|
|
@ -1,149 +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
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { checkLicense, checkLicenseGenerator } from './check_license';
|
||||
import expect from '@kbn/expect';
|
||||
import sinon from 'sinon';
|
||||
|
||||
describe('Monitoring Check License', () => {
|
||||
describe('License undeterminable', () => {
|
||||
it('null active license - results false with a message', () => {
|
||||
const result = checkLicense(null, true, 'test-cluster-abc');
|
||||
expect(result).to.eql({
|
||||
clusterAlerts: { enabled: false },
|
||||
message: `Cluster Alerts are not displayed because the [test-cluster-abc] cluster's license could not be determined.`,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Inactive license', () => {
|
||||
it('platinum inactive license - results false with a message', () => {
|
||||
const result = checkLicense('platinum', false, 'test-cluster-def');
|
||||
expect(result).to.eql({
|
||||
clusterAlerts: { enabled: false },
|
||||
message: `Cluster Alerts are not displayed because the [test-cluster-def] cluster's current license [platinum] is not active.`,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Active license', () => {
|
||||
describe('Unsupported license types', () => {
|
||||
it('basic active license - results false with a message', () => {
|
||||
const result = checkLicense('basic', true, 'test-cluster-ghi');
|
||||
expect(result).to.eql({
|
||||
clusterAlerts: { enabled: false },
|
||||
message: `Cluster Alerts are not displayed if Watcher is disabled or the [test-cluster-ghi] cluster's current license is Basic.`,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Supported license types', () => {
|
||||
it('standard active license - results true with no message', () => {
|
||||
const result = checkLicense('standard', true, 'test-cluster-jkl');
|
||||
expect(result).to.eql({
|
||||
clusterAlerts: { enabled: true },
|
||||
});
|
||||
});
|
||||
|
||||
it('gold active license - results true with no message', () => {
|
||||
const result = checkLicense('gold', true, 'test-cluster-mno');
|
||||
expect(result).to.eql({
|
||||
clusterAlerts: { enabled: true },
|
||||
});
|
||||
});
|
||||
|
||||
it('platinum active license - results true with no message', () => {
|
||||
const result = checkLicense('platinum', true, 'test-cluster-pqr');
|
||||
expect(result).to.eql({
|
||||
clusterAlerts: { enabled: true },
|
||||
});
|
||||
});
|
||||
|
||||
it('enterprise active license - results true with no message', () => {
|
||||
const result = checkLicense('enterprise', true, 'test-cluster-pqr');
|
||||
expect(result).to.eql({
|
||||
clusterAlerts: { enabled: true },
|
||||
});
|
||||
});
|
||||
|
||||
describe('Watcher is not enabled', () => {
|
||||
it('platinum active license - watcher disabled - results false with message', () => {
|
||||
const result = checkLicense('platinum', true, 'test-cluster-pqr', false);
|
||||
expect(result).to.eql({
|
||||
clusterAlerts: { enabled: false },
|
||||
message: 'Cluster Alerts are not enabled because Watcher is disabled.',
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('XPackInfo checkLicenseGenerator', () => {
|
||||
it('with deleted license', () => {
|
||||
const expected = 123;
|
||||
const checker = sinon.stub().returns(expected);
|
||||
const result = checkLicenseGenerator(null, checker);
|
||||
|
||||
expect(result).to.be(expected);
|
||||
expect(checker.withArgs(undefined, false, 'monitoring', false).called).to.be(true);
|
||||
});
|
||||
|
||||
it('license without watcher', () => {
|
||||
const expected = 123;
|
||||
const xpackInfo = {
|
||||
license: {
|
||||
getType: () => 'fake-type',
|
||||
isActive: () => true,
|
||||
},
|
||||
feature: () => null,
|
||||
};
|
||||
const checker = sinon.stub().returns(expected);
|
||||
const result = checkLicenseGenerator(xpackInfo, checker);
|
||||
|
||||
expect(result).to.be(expected);
|
||||
expect(checker.withArgs('fake-type', true, 'monitoring', false).called).to.be(true);
|
||||
});
|
||||
|
||||
it('mock license with watcher', () => {
|
||||
const expected = 123;
|
||||
const feature = sinon
|
||||
.stub()
|
||||
.withArgs('watcher')
|
||||
.returns({ isEnabled: () => true });
|
||||
const xpackInfo = {
|
||||
license: {
|
||||
getType: () => 'another-type',
|
||||
isActive: () => true,
|
||||
},
|
||||
feature,
|
||||
};
|
||||
const checker = sinon.stub().returns(expected);
|
||||
const result = checkLicenseGenerator(xpackInfo, checker);
|
||||
|
||||
expect(result).to.be(expected);
|
||||
expect(feature.withArgs('watcher').calledOnce).to.be(true);
|
||||
expect(checker.withArgs('another-type', true, 'monitoring', true).called).to.be(true);
|
||||
});
|
||||
|
||||
it('platinum license with watcher', () => {
|
||||
const xpackInfo = {
|
||||
license: {
|
||||
getType: () => 'platinum',
|
||||
isActive: () => true,
|
||||
},
|
||||
feature: () => {
|
||||
return {
|
||||
isEnabled: () => true,
|
||||
};
|
||||
},
|
||||
};
|
||||
const result = checkLicenseGenerator(xpackInfo);
|
||||
|
||||
expect(result).to.eql({ clusterAlerts: { enabled: true } });
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,47 +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
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { get } from 'lodash';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
/**
|
||||
* Determine if an API for Cluster Alerts should respond based on the license and configuration of the monitoring cluster.
|
||||
*
|
||||
* Note: This does not guarantee that any production cluster has a valid license; only that Cluster Alerts in general can be used!
|
||||
*
|
||||
* @param {Object} server Server object containing config and plugins
|
||||
* @return {Boolean} {@code true} to indicate that cluster alerts can be used.
|
||||
*/
|
||||
export function verifyMonitoringLicense(server) {
|
||||
const config = server.config();
|
||||
|
||||
// if cluster alerts are enabled, then ensure that we can use it according to the license
|
||||
if (config.get('monitoring.cluster_alerts.enabled')) {
|
||||
const xpackInfo = get(server.plugins.monitoring, 'info');
|
||||
if (xpackInfo) {
|
||||
const watcherFeature = xpackInfo.getWatcherFeature();
|
||||
return {
|
||||
enabled: watcherFeature.isEnabled,
|
||||
message: xpackInfo.getMessage(),
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
enabled: false,
|
||||
message: i18n.translate('xpack.monitoring.clusterAlerts.notDeterminedLicenseDescription', {
|
||||
defaultMessage: 'Status of Cluster Alerts feature could not be determined.',
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
enabled: false,
|
||||
message: i18n.translate('xpack.monitoring.clusterAlerts.disabledLicenseDescription', {
|
||||
defaultMessage: 'Cluster Alerts feature is disabled.',
|
||||
}),
|
||||
};
|
||||
}
|
|
@ -1,88 +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
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { verifyMonitoringLicense } from './verify_monitoring_license';
|
||||
import expect from '@kbn/expect';
|
||||
import sinon from 'sinon';
|
||||
|
||||
// TODO: tests were not running and are not up to date.
|
||||
describe.skip('Monitoring Verify License', () => {
|
||||
describe('Disabled by Configuration', () => {
|
||||
const get = sinon.stub().withArgs('xpack.monitoring.cluster_alerts.enabled').returns(false);
|
||||
const server = { config: sinon.stub().returns({ get }) };
|
||||
|
||||
it('verifyMonitoringLicense returns false without checking the license', () => {
|
||||
const verification = verifyMonitoringLicense(server);
|
||||
|
||||
expect(verification.enabled).to.be(false);
|
||||
expect(verification.message).to.be('Cluster Alerts feature is disabled.');
|
||||
|
||||
expect(get.withArgs('xpack.monitoring.cluster_alerts.enabled').calledOnce).to.be(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Enabled by Configuration', () => {
|
||||
it('verifyMonitoringLicense returns false if enabled by configuration, but not by license', () => {
|
||||
const get = sinon.stub().withArgs('xpack.monitoring.cluster_alerts.enabled').returns(true);
|
||||
const server = {
|
||||
config: sinon.stub().returns({ get }),
|
||||
plugins: { monitoring: { info: {} } },
|
||||
};
|
||||
const getLicenseCheckResults = sinon
|
||||
.stub()
|
||||
.returns({ clusterAlerts: { enabled: false }, message: 'failed!!' });
|
||||
const feature = sinon.stub().withArgs('monitoring').returns({ getLicenseCheckResults });
|
||||
|
||||
server.plugins.monitoring.info = { feature };
|
||||
|
||||
const verification = verifyMonitoringLicense(server);
|
||||
|
||||
expect(verification.enabled).to.be(false);
|
||||
expect(verification.message).to.be('failed!!');
|
||||
|
||||
expect(get.withArgs('xpack.monitoring.cluster_alerts.enabled').calledOnce).to.be(true);
|
||||
expect(feature.withArgs('monitoring').calledOnce).to.be(true);
|
||||
expect(getLicenseCheckResults.calledOnce).to.be(true);
|
||||
});
|
||||
|
||||
it('verifyMonitoringLicense returns true if enabled by configuration and by license', () => {
|
||||
const get = sinon.stub().withArgs('xpack.monitoring.cluster_alerts.enabled').returns(true);
|
||||
const server = {
|
||||
config: sinon.stub().returns({ get }),
|
||||
plugins: { monitoring: { info: {} } },
|
||||
};
|
||||
const getLicenseCheckResults = sinon.stub().returns({ clusterAlerts: { enabled: true } });
|
||||
const feature = sinon.stub().withArgs('monitoring').returns({ getLicenseCheckResults });
|
||||
|
||||
server.plugins.monitoring.info = { feature };
|
||||
|
||||
const verification = verifyMonitoringLicense(server);
|
||||
|
||||
expect(verification.enabled).to.be(true);
|
||||
expect(verification.message).to.be.undefined;
|
||||
|
||||
expect(get.withArgs('xpack.monitoring.cluster_alerts.enabled').calledOnce).to.be(true);
|
||||
expect(feature.withArgs('monitoring').calledOnce).to.be(true);
|
||||
expect(getLicenseCheckResults.calledOnce).to.be(true);
|
||||
});
|
||||
});
|
||||
|
||||
it('Monitoring feature info cannot be determined', () => {
|
||||
const get = sinon.stub().withArgs('xpack.monitoring.cluster_alerts.enabled').returns(true);
|
||||
const server = {
|
||||
config: sinon.stub().returns({ get }),
|
||||
plugins: { monitoring: undefined }, // simulate race condition
|
||||
};
|
||||
|
||||
const verification = verifyMonitoringLicense(server);
|
||||
|
||||
expect(verification.enabled).to.be(false);
|
||||
expect(verification.message).to.be('Status of Cluster Alerts feature could not be determined.');
|
||||
|
||||
expect(get.withArgs('xpack.monitoring.cluster_alerts.enabled').calledOnce).to.be(true);
|
||||
});
|
||||
});
|
|
@ -37,25 +37,9 @@ describe.skip('monitoring plugin deprecations', function () {
|
|||
expect(log).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it(`shouldn't log when cluster alerts are disabled`, function () {
|
||||
const settings = {
|
||||
cluster_alerts: {
|
||||
enabled: false,
|
||||
email_notifications: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const log = jest.fn();
|
||||
transformDeprecations(settings, fromPath, log);
|
||||
expect(log).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it(`shouldn't log when email_address is specified`, function () {
|
||||
const settings = {
|
||||
cluster_alerts: {
|
||||
enabled: true,
|
||||
email_notifications: {
|
||||
enabled: true,
|
||||
email_address: 'foo@bar.com',
|
||||
|
@ -71,7 +55,6 @@ describe.skip('monitoring plugin deprecations', function () {
|
|||
it(`should log when email_address is missing, but alerts/notifications are both enabled`, function () {
|
||||
const settings = {
|
||||
cluster_alerts: {
|
||||
enabled: true,
|
||||
email_notifications: {
|
||||
enabled: true,
|
||||
},
|
||||
|
|
|
@ -15,8 +15,6 @@ import { getKibanasForClusters } from '../kibana';
|
|||
import { getLogstashForClusters } from '../logstash';
|
||||
import { getLogstashPipelineIds } from '../logstash/get_pipeline_ids';
|
||||
import { getBeatsForClusters } from '../beats';
|
||||
import { verifyMonitoringLicense } from '../../cluster_alerts/verify_monitoring_license';
|
||||
import { checkLicense as checkLicenseForAlerts } from '../../cluster_alerts/check_license';
|
||||
import { getClustersSummary } from './get_clusters_summary';
|
||||
import {
|
||||
STANDALONE_CLUSTER_CLUSTER_UUID,
|
||||
|
@ -128,19 +126,6 @@ export async function getClustersFromRequest(
|
|||
);
|
||||
|
||||
for (const cluster of clusters) {
|
||||
const verification = verifyMonitoringLicense(req.server);
|
||||
if (!verification.enabled) {
|
||||
// return metadata detailing that alerts is disabled because of the monitoring cluster license
|
||||
cluster.alerts = {
|
||||
alertsMeta: {
|
||||
enabled: verification.enabled,
|
||||
message: verification.message, // NOTE: this is only defined when the alert feature is disabled
|
||||
},
|
||||
list: {},
|
||||
};
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!alertsClient) {
|
||||
cluster.alerts = {
|
||||
list: {},
|
||||
|
@ -148,17 +133,7 @@ export async function getClustersFromRequest(
|
|||
enabled: false,
|
||||
},
|
||||
};
|
||||
continue;
|
||||
}
|
||||
|
||||
// check the license type of the production cluster for alerts feature support
|
||||
const license = cluster.license || {};
|
||||
const prodLicenseInfo = checkLicenseForAlerts(
|
||||
license.type,
|
||||
license.status === 'active',
|
||||
'production'
|
||||
);
|
||||
if (prodLicenseInfo.clusterAlerts.enabled) {
|
||||
} else {
|
||||
try {
|
||||
cluster.alerts = {
|
||||
list: Object.keys(alertStatus).reduce((accum, alertName) => {
|
||||
|
@ -190,29 +165,7 @@ export async function getClustersFromRequest(
|
|||
},
|
||||
};
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
cluster.alerts = {
|
||||
list: {},
|
||||
alertsMeta: {
|
||||
enabled: false,
|
||||
},
|
||||
clusterMeta: {
|
||||
enabled: false,
|
||||
message: i18n.translate(
|
||||
'xpack.monitoring.clusterAlerts.unsupportedClusterAlertsDescription',
|
||||
{
|
||||
defaultMessage:
|
||||
'Cluster [{clusterName}] license type [{licenseType}] does not support Cluster Alerts',
|
||||
values: {
|
||||
clusterName: cluster.cluster_name,
|
||||
licenseType: `${license.type}`,
|
||||
},
|
||||
}
|
||||
),
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15760,15 +15760,6 @@
|
|||
"xpack.monitoring.cluster.overview.logstashPanel.withPersistentQueuesLabel": "永続キューあり",
|
||||
"xpack.monitoring.cluster.overview.pageTitle": "クラスターの概要",
|
||||
"xpack.monitoring.cluster.overviewTitle": "概要",
|
||||
"xpack.monitoring.clusterAlerts.checkLicense.licenseIsBasicDescription": "Watcher が無効になっているか、[{clusterSource}] クラスターの現在のライセンスがベーシックの場合、クラスターアラートは表示されません。",
|
||||
"xpack.monitoring.clusterAlerts.checkLicense.licenseNotActiveDescription": "[{clusterSource}] クラスターの現在のライセンス [{type}] がアクティブでないため、クラスターアラートは表示されません。",
|
||||
"xpack.monitoring.clusterAlerts.checkLicense.licenseNotDeterminedDescription": "[{clusterSource}] クラスターのライセンスが確認できなかったため、クラスターアラートは表示されません。",
|
||||
"xpack.monitoring.clusterAlerts.checkLicense.watcherIsDisabledDescription": "Watcher が無効なため、クラスターアラートを利用できません。",
|
||||
"xpack.monitoring.clusterAlerts.clusterNeedsTSLEnabledDescription": "セキュリティが有効な場合、ゴールドまたはプラチナライセンスの適用に TLS の構成が必要です。",
|
||||
"xpack.monitoring.clusterAlerts.disabledLicenseDescription": "クラスターアラート機能は無効になっています。",
|
||||
"xpack.monitoring.clusterAlerts.notDeterminedLicenseDescription": "クラスターアラート機能のステータスが確認できませんでした。",
|
||||
"xpack.monitoring.clusterAlerts.seeDocumentationDescription": "詳細はドキュメンテーションをご覧ください。",
|
||||
"xpack.monitoring.clusterAlerts.unsupportedClusterAlertsDescription": "クラスター [{clusterName}] ライセンスタイプ [{licenseType}] はクラスターアラートをサポートしていません",
|
||||
"xpack.monitoring.clusterAlertsNavigation.clusterAlertsLinkText": "クラスターアラート",
|
||||
"xpack.monitoring.clustersNavigation.clustersLinkText": "クラスター",
|
||||
"xpack.monitoring.clusterStats.uuidNotFoundErrorMessage": "選択された時間範囲にクラスターが見つかりませんでした。UUID:{clusterUuid}",
|
||||
|
|
|
@ -15984,15 +15984,6 @@
|
|||
"xpack.monitoring.cluster.overview.logstashPanel.withPersistentQueuesLabel": "持久性队列",
|
||||
"xpack.monitoring.cluster.overview.pageTitle": "集群概览",
|
||||
"xpack.monitoring.cluster.overviewTitle": "概览",
|
||||
"xpack.monitoring.clusterAlerts.checkLicense.licenseIsBasicDescription": "如果禁用了 Watcher 或 [{clusterSource}] 集群的当前许可为基本级许可,则“集群告警”将不会显示。",
|
||||
"xpack.monitoring.clusterAlerts.checkLicense.licenseNotActiveDescription": "因为 [{clusterSource}] 集群的当前许可 [{type}] 未处于活动状态,所以“集群告警”将不会显示。",
|
||||
"xpack.monitoring.clusterAlerts.checkLicense.licenseNotDeterminedDescription": "因为无法确定 [{clusterSource}] 集群的许可,所以“集群告警”将不会显示。",
|
||||
"xpack.monitoring.clusterAlerts.checkLicense.watcherIsDisabledDescription": "因为禁用了 Watcher,所以“集群告警”未启用。",
|
||||
"xpack.monitoring.clusterAlerts.clusterNeedsTSLEnabledDescription": "启用安全性时,需要配置 TLS,才能应用黄金或白金许可。",
|
||||
"xpack.monitoring.clusterAlerts.disabledLicenseDescription": "“集群告警”功能已禁用。",
|
||||
"xpack.monitoring.clusterAlerts.notDeterminedLicenseDescription": "无法确定“集群告警”功能的状态。",
|
||||
"xpack.monitoring.clusterAlerts.seeDocumentationDescription": "有关详情,请参阅文档。",
|
||||
"xpack.monitoring.clusterAlerts.unsupportedClusterAlertsDescription": "集群 [{clusterName}] 许可类型 [{licenseType}] 不支持“集群告警”",
|
||||
"xpack.monitoring.clusterAlertsNavigation.clusterAlertsLinkText": "集群告警",
|
||||
"xpack.monitoring.clustersNavigation.clustersLinkText": "集群",
|
||||
"xpack.monitoring.clusterStats.uuidNotFoundErrorMessage": "在选定时间范围内找不到该集群。UUID:{clusterUuid}",
|
||||
|
|
|
@ -102,11 +102,7 @@
|
|||
},
|
||||
"alerts": {
|
||||
"alertsMeta": {
|
||||
"enabled": false
|
||||
},
|
||||
"clusterMeta": {
|
||||
"enabled": false,
|
||||
"message": "Cluster [clustertwo] license type [basic] does not support Cluster Alerts"
|
||||
"enabled": true
|
||||
},
|
||||
"list": {}
|
||||
},
|
||||
|
|
|
@ -102,11 +102,7 @@
|
|||
},
|
||||
"alerts": {
|
||||
"alertsMeta": {
|
||||
"enabled": false
|
||||
},
|
||||
"clusterMeta": {
|
||||
"enabled": false,
|
||||
"message": "Cluster [monitoring] license type [basic] does not support Cluster Alerts"
|
||||
"enabled": true
|
||||
},
|
||||
"list": {}
|
||||
},
|
||||
|
@ -170,11 +166,7 @@
|
|||
},
|
||||
"alerts": {
|
||||
"alertsMeta": {
|
||||
"enabled": false
|
||||
},
|
||||
"clusterMeta": {
|
||||
"enabled": false,
|
||||
"message": "Cluster [] license type [undefined] does not support Cluster Alerts"
|
||||
"enabled": true
|
||||
},
|
||||
"list": {}
|
||||
},
|
||||
|
|
|
@ -109,7 +109,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
|
||||
it('primary basic cluster shows cluster metrics', async () => {
|
||||
expect(await clusterList.getClusterName(SUPPORTED_CLUSTER_UUID)).to.be('production');
|
||||
expect(await clusterList.getClusterStatus(SUPPORTED_CLUSTER_UUID)).to.be('N/A');
|
||||
expect(await clusterList.getClusterStatus(SUPPORTED_CLUSTER_UUID)).to.be('Clear');
|
||||
expect(await clusterList.getClusterNodesCount(SUPPORTED_CLUSTER_UUID)).to.be('2');
|
||||
expect(await clusterList.getClusterIndicesCount(SUPPORTED_CLUSTER_UUID)).to.be('4');
|
||||
expect(await clusterList.getClusterDataSize(SUPPORTED_CLUSTER_UUID)).to.be('1.6 MB');
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue