Skip to content

Commit

Permalink
NP Licensing service info endpoint (#51188)
Browse files Browse the repository at this point in the history
* add NP licensing service info endpoint

* call licensing/info and mark it as system to prevent session update

* add integration api test for licensing/info endpoint

* readonly for static data!
  • Loading branch information
mshustov authored Nov 20, 2019
1 parent e16e3e3 commit d61cef4
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 17 deletions.
21 changes: 20 additions & 1 deletion x-pack/plugins/licensing/public/plugin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,25 @@ describe('licensing plugin', () => {

expect(license.uid).toBe('fetched');
});

it('data re-fetch call marked as a system api', async () => {
const sessionStorage = coreMock.createStorage();
plugin = new LicensingPlugin(coreMock.createPluginInitializerContext(), sessionStorage);

const coreSetup = coreMock.createSetup();
const fetchedLicense = licenseMock.create();
coreSetup.http.get.mockResolvedValue(fetchedLicense);

const { refresh } = await plugin.setup(coreSetup);

refresh();

expect(coreSetup.http.get.mock.calls[0][1]).toMatchObject({
headers: {
'kbn-system-api': 'true',
},
});
});
});

describe('#license$', () => {
Expand Down Expand Up @@ -238,7 +257,7 @@ describe('licensing plugin', () => {
},
},
request: {
url: 'http://10.10.10.10:5601/api/xpack/v1/info',
url: 'http://10.10.10.10:5601/api/licensing/info',
},
};
expect(coreSetup.http.get).toHaveBeenCalledTimes(0);
Expand Down
40 changes: 24 additions & 16 deletions x-pack/plugins/licensing/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/

import { Subject, Subscription, merge } from 'rxjs';
import { takeUntil, tap } from 'rxjs/operators';
import { takeUntil } from 'rxjs/operators';

import { CoreSetup, Plugin, PluginInitializerContext } from 'src/core/public';

Expand All @@ -31,8 +31,9 @@ export class LicensingPlugin implements Plugin<LicensingPluginSetup> {
*/
private removeInterceptor?: () => void;
private licenseFetchSubscription?: Subscription;
private storageSubscription?: Subscription;

private infoEndpoint = '/api/xpack/v1/info';
private readonly infoEndpoint = '/api/licensing/info';
private prevSignature?: string;

constructor(
Expand Down Expand Up @@ -76,18 +77,16 @@ export class LicensingPlugin implements Plugin<LicensingPluginSetup> {
);
this.licenseFetchSubscription = fetchSubscription;

const license$ = update$.pipe(
tap(license => {
if (license.error) {
this.prevSignature = undefined;
// Prevent reusing stale license if the fetch operation fails
this.removeSaved();
} else {
this.prevSignature = license.signature;
this.save(license);
}
})
);
this.storageSubscription = update$.subscribe(license => {
if (license.isAvailable) {
this.prevSignature = license.signature;
this.save(license);
} else {
this.prevSignature = undefined;
// Prevent reusing stale license if the fetch operation fails
this.removeSaved();
}
});

this.removeInterceptor = core.http.intercept({
response: async httpResponse => {
Expand All @@ -107,7 +106,7 @@ export class LicensingPlugin implements Plugin<LicensingPluginSetup> {
refresh: () => {
manualRefresh$.next();
},
license$,
license$: update$,
};
}

Expand All @@ -124,11 +123,20 @@ export class LicensingPlugin implements Plugin<LicensingPluginSetup> {
this.licenseFetchSubscription.unsubscribe();
this.licenseFetchSubscription = undefined;
}
if (this.storageSubscription !== undefined) {
this.storageSubscription.unsubscribe();
this.storageSubscription = undefined;
}
}

private fetchLicense = async (core: CoreSetup): Promise<ILicense> => {
try {
const response = await core.http.get(this.infoEndpoint);
const response = await core.http.get(this.infoEndpoint, {
headers: {
'kbn-system-api': 'true',
},
});

return new License({
license: response.license,
features: response.features,
Expand Down
3 changes: 3 additions & 0 deletions x-pack/plugins/licensing/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import { License } from '../common/license';
import { createLicenseUpdate } from '../common/license_update';

import { ElasticsearchError, RawLicense, RawFeatures } from './types';
import { registerRoutes } from './routes';

import { LicenseConfigType } from './licensing_config';
import { createRouteHandlerContext } from './licensing_route_handler_context';

Expand Down Expand Up @@ -92,6 +94,7 @@ export class LicensingPlugin implements Plugin<LicensingPluginSetup> {
const { refresh, license$ } = this.createLicensePoller(dataClient, config.pollingFrequency);

core.http.registerRouteHandlerContext('licensing', createRouteHandlerContext(license$));
registerRoutes(core.http.createRouter());

return {
refresh,
Expand Down
11 changes: 11 additions & 0 deletions x-pack/plugins/licensing/server/routes/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
* 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 { IRouter } from 'src/core/server';
import { registerInfoRoute } from './info';

export function registerRoutes(router: IRouter) {
registerInfoRoute(router);
}
14 changes: 14 additions & 0 deletions x-pack/plugins/licensing/server/routes/info.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* 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 { IRouter } from 'src/core/server';

export function registerInfoRoute(router: IRouter) {
router.get({ path: '/api/licensing/info', validate: false }, (context, request, response) => {
return response.ok({
body: context.licensing.license,
});
});
}
1 change: 1 addition & 0 deletions x-pack/test/api_integration/apis/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,6 @@ export default function ({ loadTestFile }) {
loadTestFile(require.resolve('./siem'));
loadTestFile(require.resolve('./short_urls'));
loadTestFile(require.resolve('./lens'));
loadTestFile(require.resolve('./licensing'));
});
}
13 changes: 13 additions & 0 deletions x-pack/test/api_integration/apis/licensing/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* 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 { FtrProviderContext } from '../../ftr_provider_context';

export default function licensingIntegrationTests({ loadTestFile }: FtrProviderContext) {
describe('Licensing', () => {
loadTestFile(require.resolve('./info'));
});
}
24 changes: 24 additions & 0 deletions x-pack/test/api_integration/apis/licensing/info.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* 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 expect from '@kbn/expect';
import { FtrProviderContext } from '../../ftr_provider_context';

export default function({ getService }: FtrProviderContext) {
const supertest = getService('supertest');

describe('Info', () => {
describe('GET /api/licensing/info', () => {
it('returns licensing information', async () => {
const response = await supertest.get('/api/licensing/info').expect(200);

expect(response.body).property('features');
expect(response.body).property('license');
expect(response.body).property('signature');
});
});
});
}

0 comments on commit d61cef4

Please sign in to comment.