Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use new ES client for licensing plugin #92143

Merged
5 changes: 0 additions & 5 deletions x-pack/plugins/licensing/server/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,9 @@ const createSetupMock = (): jest.Mocked<LicensingPluginSetup> => {
const mock = {
license$: new BehaviorSubject(license),
refresh: jest.fn(),
createLicensePoller: jest.fn(),
featureUsage: featureUsageMock.createSetup(),
};
mock.refresh.mockResolvedValue(license);
mock.createLicensePoller.mockReturnValue({
license$: mock.license$,
refresh: mock.refresh,
});

return mock;
};
Expand Down
128 changes: 69 additions & 59 deletions x-pack/plugins/licensing/server/plugin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,43 +6,42 @@
*/

import { take, toArray } from 'rxjs/operators';
import { estypes } from '@elastic/elasticsearch';
import moment from 'moment';
import { LicenseType } from '../common/types';
import { ElasticsearchError, RawLicense } from './types';
import { ElasticsearchError } from './types';
import { LicensingPlugin } from './plugin';
import {
coreMock,
elasticsearchServiceMock,
loggingSystemMock,
} from '../../../../src/core/server/mocks';
import { ILegacyClusterClient } from '../../../../src/core/server/';
import { IClusterClient } from '../../../../src/core/server';

function buildRawLicense(options: Partial<RawLicense> = {}): RawLicense {
const defaultRawLicense: RawLicense = {
function buildRawLicense(
options: Partial<estypes.XpackInfoMinimalLicenseInformation> = {}
): estypes.XpackInfoMinimalLicenseInformation {
return {
uid: 'uid-000000001234',
status: 'active',
type: 'basic',
mode: 'basic',
expiry_date_in_millis: 1000,
...options,
};
return Object.assign(defaultRawLicense, options);
}

const flushPromises = (ms = 50) => new Promise((res) => setTimeout(res, ms));

function createCoreSetupWith(esClient: ILegacyClusterClient) {
function createCoreSetupWith(esClient: IClusterClient) {
const coreSetup = coreMock.createSetup();
const coreStart = coreMock.createStart();
coreSetup.getStartServices.mockResolvedValue([
{
...coreStart,
elasticsearch: {
...coreStart.elasticsearch,
legacy: {
...coreStart.elasticsearch.legacy,
client: esClient,
createClient: jest.fn(),
},
client: esClient,
},
},
{},
Expand All @@ -52,6 +51,16 @@ function createCoreSetupWith(esClient: ILegacyClusterClient) {
}

describe('licensing plugin', () => {
const createEsClient = (response?: Record<string, any>) => {
const client = elasticsearchServiceMock.createClusterClient();
if (response) {
client.asInternalUser.xpack.info.mockReturnValue(
elasticsearchServiceMock.createSuccessTransportRequestPromise(response as any)
);
}
return client;
};

describe('#start', () => {
describe('#license$', () => {
let plugin: LicensingPlugin;
Expand All @@ -69,8 +78,7 @@ describe('licensing plugin', () => {
});

it('returns license', async () => {
const esClient = elasticsearchServiceMock.createLegacyClusterClient();
esClient.callAsInternalUser.mockResolvedValue({
const esClient = createEsClient({
license: buildRawLicense(),
features: {},
});
Expand All @@ -83,8 +91,7 @@ describe('licensing plugin', () => {
});

it('calls `callAsInternalUser` with the correct parameters', async () => {
const esClient = elasticsearchServiceMock.createLegacyClusterClient();
esClient.callAsInternalUser.mockResolvedValue({
const esClient = createEsClient({
license: buildRawLicense(),
features: {},
});
Expand All @@ -94,23 +101,22 @@ describe('licensing plugin', () => {
const { license$ } = await plugin.start();
await license$.pipe(take(1)).toPromise();

expect(esClient.callAsInternalUser).toHaveBeenCalledTimes(1);
expect(esClient.callAsInternalUser).toHaveBeenCalledWith('transport.request', {
method: 'GET',
path: '/_xpack?accept_enterprise=true',
expect(esClient.asInternalUser.xpack.info).toHaveBeenCalledTimes(1);
expect(esClient.asInternalUser.xpack.info).toHaveBeenCalledWith({
accept_enterprise: true,
});
});

it('observable receives updated licenses', async () => {
const types: LicenseType[] = ['basic', 'gold', 'platinum'];

const esClient = elasticsearchServiceMock.createLegacyClusterClient();
esClient.callAsInternalUser.mockImplementation(() =>
Promise.resolve({
const esClient = createEsClient();
esClient.asInternalUser.xpack.info.mockImplementation(() => {
return elasticsearchServiceMock.createSuccessTransportRequestPromise({
license: buildRawLicense({ type: types.shift() }),
features: {},
})
);
} as estypes.XpackInfoResponse);
});

const coreSetup = createCoreSetupWith(esClient);
await plugin.setup(coreSetup);
Expand All @@ -123,8 +129,8 @@ describe('licensing plugin', () => {
});

it('returns a license with error when request fails', async () => {
const esClient = elasticsearchServiceMock.createLegacyClusterClient();
esClient.callAsInternalUser.mockRejectedValue(new Error('test'));
const esClient = createEsClient();
esClient.asInternalUser.xpack.info.mockRejectedValue(new Error('test'));

const coreSetup = createCoreSetupWith(esClient);
await plugin.setup(coreSetup);
Expand All @@ -136,10 +142,10 @@ describe('licensing plugin', () => {
});

it('generate error message when x-pack plugin was not installed', async () => {
const esClient = elasticsearchServiceMock.createLegacyClusterClient();
const esClient = createEsClient();
const error: ElasticsearchError = new Error('reason');
error.status = 400;
esClient.callAsInternalUser.mockRejectedValue(error);
esClient.asInternalUser.xpack.info.mockRejectedValue(error);

const coreSetup = createCoreSetupWith(esClient);
await plugin.setup(coreSetup);
Expand All @@ -154,26 +160,35 @@ describe('licensing plugin', () => {
const error1 = new Error('reason-1');
const error2 = new Error('reason-2');

const esClient = elasticsearchServiceMock.createLegacyClusterClient();

esClient.callAsInternalUser
.mockRejectedValueOnce(error1)
.mockRejectedValueOnce(error2)
.mockResolvedValue({ license: buildRawLicense(), features: {} });
const esClient = createEsClient();
let i = 0;
esClient.asInternalUser.xpack.info.mockImplementation(() => {
i++;
if (i === 1) {
return elasticsearchServiceMock.createErrorTransportRequestPromise(error1);
}
if (i === 2) {
return elasticsearchServiceMock.createErrorTransportRequestPromise(error2);
}
return elasticsearchServiceMock.createSuccessTransportRequestPromise({
license: buildRawLicense(),
features: {},
} as estypes.XpackInfoResponse);
});

const coreSetup = createCoreSetupWith(esClient);
await plugin.setup(coreSetup);
const { license$ } = await plugin.start();

const [first, second, third] = await license$.pipe(take(3), toArray()).toPromise();

expect(first.error).toBe(error1.message);
expect(second.error).toBe(error2.message);
expect(third.type).toBe('basic');
});

it('fetch license immediately without subscriptions', async () => {
const esClient = elasticsearchServiceMock.createLegacyClusterClient();
esClient.callAsInternalUser.mockResolvedValue({
const esClient = createEsClient({
license: buildRawLicense(),
features: {},
});
Expand All @@ -184,12 +199,11 @@ describe('licensing plugin', () => {

await flushPromises();

expect(esClient.callAsInternalUser).toHaveBeenCalledTimes(1);
expect(esClient.asInternalUser.xpack.info).toHaveBeenCalledTimes(1);
});

it('logs license details without subscriptions', async () => {
const esClient = elasticsearchServiceMock.createLegacyClusterClient();
esClient.callAsInternalUser.mockResolvedValue({
const esClient = createEsClient({
license: buildRawLicense(),
features: {},
});
Expand All @@ -214,13 +228,13 @@ describe('licensing plugin', () => {
it('generates signature based on fetched license content', async () => {
const types: LicenseType[] = ['basic', 'gold', 'basic'];

const esClient = elasticsearchServiceMock.createLegacyClusterClient();
esClient.callAsInternalUser.mockImplementation(() =>
Promise.resolve({
const esClient = createEsClient();
esClient.asInternalUser.xpack.info.mockImplementation(() => {
return elasticsearchServiceMock.createSuccessTransportRequestPromise({
license: buildRawLicense({ type: types.shift() }),
features: {},
})
);
} as estypes.XpackInfoResponse);
});

const coreSetup = createCoreSetupWith(esClient);
await plugin.setup(coreSetup);
Expand All @@ -245,8 +259,7 @@ describe('licensing plugin', () => {
api_polling_frequency: moment.duration(50000),
})
);
const esClient = elasticsearchServiceMock.createLegacyClusterClient();
esClient.callAsInternalUser.mockResolvedValue({
const esClient = createEsClient({
license: buildRawLicense(),
features: {},
});
Expand All @@ -255,14 +268,14 @@ describe('licensing plugin', () => {
await plugin.setup(coreSetup);
const { refresh, license$ } = await plugin.start();

expect(esClient.callAsInternalUser).toHaveBeenCalledTimes(0);
expect(esClient.asInternalUser.xpack.info).toHaveBeenCalledTimes(0);

await license$.pipe(take(1)).toPromise();
expect(esClient.callAsInternalUser).toHaveBeenCalledTimes(1);
expect(esClient.asInternalUser.xpack.info).toHaveBeenCalledTimes(1);

refresh();
await flushPromises();
expect(esClient.callAsInternalUser).toHaveBeenCalledTimes(2);
expect(esClient.asInternalUser.xpack.info).toHaveBeenCalledTimes(2);
});
});

Expand All @@ -280,17 +293,15 @@ describe('licensing plugin', () => {
})
);

const esClient = elasticsearchServiceMock.createLegacyClusterClient();
esClient.callAsInternalUser.mockResolvedValue({
const esClient = createEsClient({
license: buildRawLicense(),
features: {},
});
const coreSetup = createCoreSetupWith(esClient);
await plugin.setup(coreSetup);
const { createLicensePoller, license$ } = await plugin.start();

const customClient = elasticsearchServiceMock.createLegacyClusterClient();
customClient.callAsInternalUser.mockResolvedValue({
const customClient = createEsClient({
license: buildRawLicense({ type: 'gold' }),
features: {},
});
Expand All @@ -300,10 +311,10 @@ describe('licensing plugin', () => {
customClient,
customPollingFrequency
);
expect(customClient.callAsInternalUser).toHaveBeenCalledTimes(0);
expect(customClient.asInternalUser.xpack.info).toHaveBeenCalledTimes(0);

const customLicense = await customLicense$.pipe(take(1)).toPromise();
expect(customClient.callAsInternalUser).toHaveBeenCalledTimes(1);
expect(customClient.asInternalUser.xpack.info).toHaveBeenCalledTimes(1);

await flushPromises(customPollingFrequency * 1.5);

Expand All @@ -324,18 +335,17 @@ describe('licensing plugin', () => {
await plugin.setup(coreSetup);
const { createLicensePoller } = await plugin.start();

const customClient = elasticsearchServiceMock.createLegacyClusterClient();
customClient.callAsInternalUser.mockResolvedValue({
const customClient = createEsClient({
license: buildRawLicense({ type: 'gold' }),
features: {},
});

const { license$, refresh } = createLicensePoller(customClient, 10000);
expect(customClient.callAsInternalUser).toHaveBeenCalledTimes(0);
expect(customClient.asInternalUser.xpack.info).toHaveBeenCalledTimes(0);

await refresh();

expect(customClient.callAsInternalUser).toHaveBeenCalledTimes(1);
expect(customClient.asInternalUser.xpack.info).toHaveBeenCalledTimes(1);
const license = await license$.pipe(take(1)).toPromise();
expect(license.type).toBe('gold');
});
Expand Down
Loading