mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
Deprecate xpack:defaultAdminEmail for monitoring alerts (#22195)
This commit is contained in:
parent
5f02f3e4ea
commit
5f96c903f3
8 changed files with 245 additions and 45 deletions
|
@ -46,8 +46,6 @@ To receive email notifications for the Cluster Alerts:
|
|||
|
||||
1. Configure an email account as described in
|
||||
{xpack-ref}/actions-email.html#configuring-email[Configuring Email Accounts].
|
||||
2. Navigate to the *Management* page in {kib}.
|
||||
3. Go to the *Advanced Settings* page, find the `xpack:defaultAdminEmail`
|
||||
setting, and enter your email address.
|
||||
2. Configure the `xpack.monitoring.cluster_alerts.email_notifications.email_address` setting in `kibana.yml` with your email address.
|
||||
|
||||
Email notifications are sent only when Cluster Alerts are triggered and resolved.
|
||||
|
|
|
@ -112,4 +112,66 @@ describe('monitoring plugin deprecations', function () {
|
|||
expect(log.called).to.be(false);
|
||||
});
|
||||
|
||||
describe('cluster_alerts.email_notifications.email_address', function () {
|
||||
it(`shouldn't log when email notifications are disabled`, function () {
|
||||
const settings = {
|
||||
cluster_alerts: {
|
||||
email_notifications: {
|
||||
enabled: false
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const log = sinon.spy();
|
||||
transformDeprecations(settings, log);
|
||||
expect(log.called).to.be(false);
|
||||
});
|
||||
|
||||
it(`shouldn't log when cluster alerts are disabled`, function () {
|
||||
const settings = {
|
||||
cluster_alerts: {
|
||||
enabled: false,
|
||||
email_notifications: {
|
||||
enabled: true
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const log = sinon.spy();
|
||||
transformDeprecations(settings, log);
|
||||
expect(log.called).to.be(false);
|
||||
});
|
||||
|
||||
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'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const log = sinon.spy();
|
||||
transformDeprecations(settings, log);
|
||||
expect(log.called).to.be(false);
|
||||
});
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const log = sinon.spy();
|
||||
transformDeprecations(settings, log);
|
||||
expect(log.called).to.be(true);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -94,7 +94,7 @@ export const CALCULATE_DURATION_UNTIL = 'until';
|
|||
/**
|
||||
* In order to show ML Jobs tab in the Elasticsearch section / tab navigation, license must be supported
|
||||
*/
|
||||
export const ML_SUPPORTED_LICENSES = [ 'trial', 'platinum' ];
|
||||
export const ML_SUPPORTED_LICENSES = ['trial', 'platinum'];
|
||||
|
||||
/**
|
||||
* Metadata service URLs for the different cloud services that have constant URLs (e.g., unlike GCP, which is a constant prefix).
|
||||
|
@ -135,7 +135,12 @@ export const DEFAULT_NO_DATA_MESSAGE_WITH_FILTER = (
|
|||
);
|
||||
|
||||
export const TABLE_ACTION_UPDATE_FILTER = 'UPDATE_FILTER';
|
||||
export const TABLE_ACTION_RESET_PAGING = 'RESET_PAGING';
|
||||
export const TABLE_ACTION_RESET_PAGING = 'RESET_PAGING';
|
||||
|
||||
export const DEBOUNCE_SLOW_MS = 17; // roughly how long it takes to render a frame at 60fps
|
||||
export const DEBOUNCE_FAST_MS = 10; // roughly how long it takes to render a frame at 100fps
|
||||
|
||||
/**
|
||||
* Configuration key for setting the email address used for cluster alert notifications.
|
||||
*/
|
||||
export const CLUSTER_ALERTS_ADDRESS_CONFIG_KEY = 'cluster_alerts.email_notifications.email_address';
|
||||
|
|
|
@ -13,7 +13,7 @@ import { XPACK_INFO_API_DEFAULT_POLL_FREQUENCY_IN_MILLIS } from '../../server/li
|
|||
*/
|
||||
export const config = (Joi) => {
|
||||
const { array, boolean, number, object, string } = Joi;
|
||||
const DEFAULT_REQUEST_HEADERS = [ 'authorization' ];
|
||||
const DEFAULT_REQUEST_HEADERS = ['authorization'];
|
||||
|
||||
return object({
|
||||
ccs: object({
|
||||
|
@ -49,7 +49,8 @@ export const config = (Joi) => {
|
|||
enabled: boolean().default(true),
|
||||
index: string().default('.monitoring-alerts-6'),
|
||||
email_notifications: object({
|
||||
enabled: boolean().default(true)
|
||||
enabled: boolean().default(true),
|
||||
email_address: string().email(),
|
||||
}).default()
|
||||
}).default(),
|
||||
xpack_api_polling_frequency_millis: number().default(XPACK_INFO_API_DEFAULT_POLL_FREQUENCY_IN_MILLIS),
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
import { get, has, set } from 'lodash';
|
||||
import { CLUSTER_ALERTS_ADDRESS_CONFIG_KEY } from './common/constants';
|
||||
|
||||
/**
|
||||
* Re-writes deprecated user-defined config settings and logs warnings as a
|
||||
|
@ -29,12 +30,19 @@ export const deprecations = ({ rename }) => {
|
|||
delete settings.elasticsearch.ssl.verify;
|
||||
|
||||
log('Config key "xpack.monitoring.elasticsearch.ssl.verify" is deprecated. ' +
|
||||
'It has been replaced with "xpack.monitoring.elasticsearch.ssl.verificationMode"');
|
||||
'It has been replaced with "xpack.monitoring.elasticsearch.ssl.verificationMode"');
|
||||
},
|
||||
(settings, log) => {
|
||||
if (has(settings, 'report_stats')) {
|
||||
log('Config key "xpack.monitoring.report_stats" is deprecated and will be removed in 7.0. ' +
|
||||
'Use "xpack.xpack_main.telemetry.enabled" instead.');
|
||||
'Use "xpack.xpack_main.telemetry.enabled" instead.');
|
||||
}
|
||||
},
|
||||
(settings, log) => {
|
||||
const clusterAlertsEnabled = get(settings, 'cluster_alerts.enabled');
|
||||
const emailNotificationsEnabled = clusterAlertsEnabled && get(settings, 'cluster_alerts.email_notifications.enabled');
|
||||
if (emailNotificationsEnabled && !get(settings, CLUSTER_ALERTS_ADDRESS_CONFIG_KEY)) {
|
||||
log(`Config key "${CLUSTER_ALERTS_ADDRESS_CONFIG_KEY}" will be required for email notifications to work in 7.0."`);
|
||||
}
|
||||
},
|
||||
];
|
||||
|
|
|
@ -8,27 +8,31 @@ import expect from 'expect.js';
|
|||
import { checkForEmailValue } from '../get_settings_collector';
|
||||
|
||||
describe('getSettingsCollector / checkForEmailValue', () => {
|
||||
const mockLogger = {
|
||||
warn: () => { }
|
||||
};
|
||||
|
||||
it('ignores shouldUseNull=true value and returns email if email value if one is set', async () => {
|
||||
const shouldUseNull = true;
|
||||
const getDefaultAdminEmailMock = () => 'test@elastic.co';
|
||||
expect(await checkForEmailValue(undefined, undefined, shouldUseNull, getDefaultAdminEmailMock)).to.be('test@elastic.co');
|
||||
expect(await checkForEmailValue(undefined, undefined, mockLogger, shouldUseNull, getDefaultAdminEmailMock)).to.be('test@elastic.co');
|
||||
});
|
||||
|
||||
it('ignores shouldUseNull=false value and returns email if email value if one is set', async () => {
|
||||
const shouldUseNull = false;
|
||||
const getDefaultAdminEmailMock = () => 'test@elastic.co';
|
||||
expect(await checkForEmailValue(undefined, undefined, shouldUseNull, getDefaultAdminEmailMock)).to.be('test@elastic.co');
|
||||
expect(await checkForEmailValue(undefined, undefined, mockLogger, shouldUseNull, getDefaultAdminEmailMock)).to.be('test@elastic.co');
|
||||
});
|
||||
|
||||
it('returns a null if no email value is set and null is allowed', async () => {
|
||||
const shouldUseNull = true;
|
||||
const getDefaultAdminEmailMock = () => null;
|
||||
expect(await checkForEmailValue(undefined, undefined, shouldUseNull, getDefaultAdminEmailMock)).to.be(null);
|
||||
expect(await checkForEmailValue(undefined, undefined, mockLogger, shouldUseNull, getDefaultAdminEmailMock)).to.be(null);
|
||||
});
|
||||
|
||||
it('returns undefined if no email value is set and null is not allowed', async () => {
|
||||
const shouldUseNull = false;
|
||||
const getDefaultAdminEmailMock = () => null;
|
||||
expect(await checkForEmailValue(undefined, undefined, shouldUseNull, getDefaultAdminEmailMock)).to.be(undefined);
|
||||
expect(await checkForEmailValue(undefined, undefined, mockLogger, shouldUseNull, getDefaultAdminEmailMock)).to.be(undefined);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -9,16 +9,23 @@ import sinon from 'sinon';
|
|||
import { set } from 'lodash';
|
||||
|
||||
import { XPACK_DEFAULT_ADMIN_EMAIL_UI_SETTING } from '../../../../../../server/lib/constants';
|
||||
import { getDefaultAdminEmail } from '../get_settings_collector';
|
||||
import { getDefaultAdminEmail, resetDeprecationWarning } from '../get_settings_collector';
|
||||
import { CLUSTER_ALERTS_ADDRESS_CONFIG_KEY } from '../../../../common/constants';
|
||||
|
||||
describe('getSettingsCollector / getDefaultAdminEmail', () => {
|
||||
function setup({ enabled = true, docExists = true, adminEmail = 'admin@email.com' }) {
|
||||
function setup({ enabled = true, docExists = true, defaultAdminEmail = 'default-admin@email.com', adminEmail = null }) {
|
||||
const config = { get: sinon.stub() };
|
||||
|
||||
config.get
|
||||
.withArgs('xpack.monitoring.cluster_alerts.email_notifications.enabled')
|
||||
.returns(enabled);
|
||||
|
||||
if (adminEmail) {
|
||||
config.get
|
||||
.withArgs(`xpack.monitoring.${CLUSTER_ALERTS_ADDRESS_CONFIG_KEY}`)
|
||||
.returns(adminEmail);
|
||||
}
|
||||
|
||||
config.get
|
||||
.withArgs('kibana.index')
|
||||
.returns('.kibana');
|
||||
|
@ -29,8 +36,8 @@ describe('getSettingsCollector / getDefaultAdminEmail', () => {
|
|||
|
||||
const doc = {};
|
||||
if (docExists) {
|
||||
if (adminEmail) {
|
||||
set(doc, ['_source', 'config', XPACK_DEFAULT_ADMIN_EMAIL_UI_SETTING], adminEmail);
|
||||
if (defaultAdminEmail) {
|
||||
set(doc, ['_source', 'config', XPACK_DEFAULT_ADMIN_EMAIL_UI_SETTING], defaultAdminEmail);
|
||||
} else {
|
||||
set(doc, '_source.config', {});
|
||||
}
|
||||
|
@ -46,41 +53,131 @@ describe('getSettingsCollector / getDefaultAdminEmail', () => {
|
|||
}))
|
||||
.returns(doc);
|
||||
|
||||
const log = {
|
||||
warn: sinon.stub()
|
||||
};
|
||||
|
||||
return {
|
||||
config,
|
||||
callCluster
|
||||
callCluster,
|
||||
log,
|
||||
};
|
||||
}
|
||||
|
||||
describe('xpack.monitoring.cluster_alerts.email_notifications.enabled = false', () => {
|
||||
it('returns null', async () => {
|
||||
const { config, callCluster } = setup({ enabled: false });
|
||||
expect(await getDefaultAdminEmail(config, callCluster)).to.be(null);
|
||||
sinon.assert.notCalled(callCluster);
|
||||
describe('using xpack:defaultAdminEmail', () => {
|
||||
beforeEach(() => {
|
||||
resetDeprecationWarning();
|
||||
});
|
||||
|
||||
describe('xpack.monitoring.cluster_alerts.email_notifications.enabled = false', () => {
|
||||
|
||||
it('returns null', async () => {
|
||||
const { config, callCluster, log } = setup({ enabled: false });
|
||||
expect(await getDefaultAdminEmail(config, callCluster, log)).to.be(null);
|
||||
sinon.assert.notCalled(callCluster);
|
||||
});
|
||||
|
||||
it('does not log a deprecation warning', async () => {
|
||||
const { config, callCluster, log } = setup({ enabled: false });
|
||||
await getDefaultAdminEmail(config, callCluster, log);
|
||||
sinon.assert.notCalled(log.warn);
|
||||
});
|
||||
});
|
||||
|
||||
describe('doc does not exist', () => {
|
||||
it('returns null', async () => {
|
||||
const { config, callCluster, log } = setup({ docExists: false });
|
||||
expect(await getDefaultAdminEmail(config, callCluster, log)).to.be(null);
|
||||
sinon.assert.calledOnce(callCluster);
|
||||
});
|
||||
|
||||
it('logs a deprecation warning', async () => {
|
||||
const { config, callCluster, log } = setup({ docExists: false });
|
||||
await getDefaultAdminEmail(config, callCluster, log);
|
||||
sinon.assert.calledOnce(log.warn);
|
||||
});
|
||||
});
|
||||
|
||||
describe('value is not defined', () => {
|
||||
it('returns null', async () => {
|
||||
const { config, callCluster, log } = setup({ defaultAdminEmail: false });
|
||||
expect(await getDefaultAdminEmail(config, callCluster, log)).to.be(null);
|
||||
sinon.assert.calledOnce(callCluster);
|
||||
});
|
||||
|
||||
it('logs a deprecation warning', async () => {
|
||||
const { config, callCluster, log } = setup({ defaultAdminEmail: false });
|
||||
await getDefaultAdminEmail(config, callCluster, log);
|
||||
sinon.assert.calledOnce(log.warn);
|
||||
});
|
||||
});
|
||||
|
||||
describe('value is defined', () => {
|
||||
it('returns value', async () => {
|
||||
const { config, callCluster, log } = setup({ defaultAdminEmail: 'hello@world' });
|
||||
expect(await getDefaultAdminEmail(config, callCluster, log)).to.be('hello@world');
|
||||
sinon.assert.calledOnce(callCluster);
|
||||
});
|
||||
|
||||
it('logs a deprecation warning', async () => {
|
||||
const { config, callCluster, log } = setup({ defaultAdminEmail: 'hello@world' });
|
||||
await getDefaultAdminEmail(config, callCluster, log);
|
||||
sinon.assert.calledOnce(log.warn);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('doc does not exist', () => {
|
||||
it('returns null', async () => {
|
||||
const { config, callCluster } = setup({ docExists: false });
|
||||
expect(await getDefaultAdminEmail(config, callCluster)).to.be(null);
|
||||
sinon.assert.calledOnce(callCluster);
|
||||
describe('using xpack.monitoring.cluster_alerts.email_notifications.email_address', () => {
|
||||
beforeEach(() => {
|
||||
resetDeprecationWarning();
|
||||
});
|
||||
});
|
||||
|
||||
describe('value is not defined', () => {
|
||||
it('returns null', async () => {
|
||||
const { config, callCluster } = setup({ adminEmail: false });
|
||||
expect(await getDefaultAdminEmail(config, callCluster)).to.be(null);
|
||||
sinon.assert.calledOnce(callCluster);
|
||||
describe('xpack.monitoring.cluster_alerts.email_notifications.enabled = false', () => {
|
||||
it('returns null', async () => {
|
||||
const { config, callCluster, log } = setup({ enabled: false });
|
||||
expect(await getDefaultAdminEmail(config, callCluster, log)).to.be(null);
|
||||
sinon.assert.notCalled(callCluster);
|
||||
});
|
||||
|
||||
it('does not log a deprecation warning', async () => {
|
||||
const { config, callCluster, log } = setup({ enabled: false });
|
||||
await getDefaultAdminEmail(config, callCluster, log);
|
||||
sinon.assert.notCalled(log.warn);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('value is defined', () => {
|
||||
it('returns value', async () => {
|
||||
const { config, callCluster } = setup({ adminEmail: 'hello@world' });
|
||||
expect(await getDefaultAdminEmail(config, callCluster)).to.be('hello@world');
|
||||
sinon.assert.calledOnce(callCluster);
|
||||
describe('value is not defined', () => {
|
||||
it('returns value from xpack:defaultAdminEmail', async () => {
|
||||
const { config, callCluster, log } = setup({
|
||||
defaultAdminEmail: 'default-admin@email.com',
|
||||
adminEmail: false
|
||||
});
|
||||
expect(await getDefaultAdminEmail(config, callCluster, log)).to.be('default-admin@email.com');
|
||||
sinon.assert.calledOnce(callCluster);
|
||||
});
|
||||
|
||||
it('logs a deprecation warning', async () => {
|
||||
const { config, callCluster, log } = setup({
|
||||
defaultAdminEmail: 'default-admin@email.com',
|
||||
adminEmail: false
|
||||
});
|
||||
await getDefaultAdminEmail(config, callCluster, log);
|
||||
sinon.assert.calledOnce(log.warn);
|
||||
});
|
||||
});
|
||||
|
||||
describe('value is defined', () => {
|
||||
it('returns value', async () => {
|
||||
const { config, callCluster, log } = setup({ adminEmail: 'hello@world' });
|
||||
expect(await getDefaultAdminEmail(config, callCluster, log)).to.be('hello@world');
|
||||
sinon.assert.notCalled(callCluster);
|
||||
});
|
||||
|
||||
it('does not log a deprecation warning', async () => {
|
||||
const { config, callCluster, log } = setup({ adminEmail: 'hello@world' });
|
||||
await getDefaultAdminEmail(config, callCluster, log);
|
||||
sinon.assert.notCalled(log.warn);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -6,24 +6,48 @@
|
|||
|
||||
import { get } from 'lodash';
|
||||
import { XPACK_DEFAULT_ADMIN_EMAIL_UI_SETTING } from '../../../../../server/lib/constants';
|
||||
import { KIBANA_SETTINGS_TYPE } from '../../../common/constants';
|
||||
import { CLUSTER_ALERTS_ADDRESS_CONFIG_KEY, KIBANA_SETTINGS_TYPE } from '../../../common/constants';
|
||||
|
||||
let loggedDeprecationWarning = false;
|
||||
|
||||
export function resetDeprecationWarning() {
|
||||
loggedDeprecationWarning = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if Cluster Alert email notifications is enabled in config
|
||||
* If so, use uiSettings API to fetch the X-Pack default admin email
|
||||
*/
|
||||
export async function getDefaultAdminEmail(config, callCluster) {
|
||||
export async function getDefaultAdminEmail(config, callCluster, log) {
|
||||
if (!config.get('xpack.monitoring.cluster_alerts.email_notifications.enabled')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const emailAddressConfigKey = `xpack.monitoring.${CLUSTER_ALERTS_ADDRESS_CONFIG_KEY}`;
|
||||
const configuredEmailAddress = config.get(emailAddressConfigKey);
|
||||
|
||||
if (configuredEmailAddress) {
|
||||
return configuredEmailAddress;
|
||||
}
|
||||
|
||||
// DEPRECATED (Remove below in 7.0): If an email address is not configured in kibana.yml, then fallback to xpack:defaultAdminEmail
|
||||
if (!loggedDeprecationWarning) {
|
||||
const message = (
|
||||
`Monitoring is using ${XPACK_DEFAULT_ADMIN_EMAIL_UI_SETTING} for cluster alert notifications, ` +
|
||||
`which will not be supported in Kibana 7.0. Please configure ${emailAddressConfigKey} in your kibana.yml settings`
|
||||
);
|
||||
|
||||
log.warn(message);
|
||||
loggedDeprecationWarning = true;
|
||||
}
|
||||
|
||||
const index = config.get('kibana.index');
|
||||
const version = config.get('pkg.version');
|
||||
const uiSettingsDoc = await callCluster('get', {
|
||||
index,
|
||||
type: 'doc',
|
||||
id: `config:${version}`,
|
||||
ignore: [ 400, 404 ] // 400 if the index is closed, 404 if it does not exist
|
||||
ignore: [400, 404] // 400 if the index is closed, 404 if it does not exist
|
||||
});
|
||||
|
||||
return get(uiSettingsDoc, ['_source', 'config', XPACK_DEFAULT_ADMIN_EMAIL_UI_SETTING], null);
|
||||
|
@ -35,10 +59,11 @@ let shouldUseNull = true;
|
|||
export async function checkForEmailValue(
|
||||
config,
|
||||
callCluster,
|
||||
log,
|
||||
_shouldUseNull = shouldUseNull,
|
||||
_getDefaultAdminEmail = getDefaultAdminEmail
|
||||
) {
|
||||
const defaultAdminEmail = await _getDefaultAdminEmail(config, callCluster);
|
||||
const defaultAdminEmail = await _getDefaultAdminEmail(config, callCluster, log);
|
||||
|
||||
// Allow null so clearing the advanced setting will be reflected in the data
|
||||
const isAcceptableNull = defaultAdminEmail === null && _shouldUseNull;
|
||||
|
@ -61,7 +86,7 @@ export function getSettingsCollector(server) {
|
|||
type: KIBANA_SETTINGS_TYPE,
|
||||
async fetch(callCluster) {
|
||||
let kibanaSettingsData;
|
||||
const defaultAdminEmail = await checkForEmailValue(config, callCluster);
|
||||
const defaultAdminEmail = await checkForEmailValue(config, callCluster, this.log);
|
||||
|
||||
// skip everything if defaultAdminEmail === undefined
|
||||
if (defaultAdminEmail || (defaultAdminEmail === null && shouldUseNull)) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue