Skip to content

Commit

Permalink
Add x-pack plugin for new platform server licensing information (elas…
Browse files Browse the repository at this point in the history
…tic#43623) (elastic#46920)

* Add x-pack plugin for new platform server licensing information

* Update x-pack translations

* Implement core plugin interface for licensing plugin:

* Rename references to service to plugin

* Use CoreStart in licensing start method

* Fix outstanding reference error

* Fix type check errors

* Address outstanding review comments

* Fix type error in tests

* Address review comments, move polling logic to standalone

* Split up test files

* Fix bad reference in test

* Use relative reference to poller util

* Add more plugin tests to address review comments

* Fix different manners of config generation in licensing plugin

* Update test fixtures

* Fix path to test fixtures
  • Loading branch information
mshustov authored Sep 30, 2019
1 parent d8392c4 commit c05b383
Show file tree
Hide file tree
Showing 17 changed files with 1,098 additions and 6 deletions.
70 changes: 70 additions & 0 deletions src/core/utils/poller.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import { Poller } from './poller';

const delay = (duration: number) => new Promise(r => setTimeout(r, duration));

describe('Poller', () => {
let handler: jest.Mock<any, any>;
let poller: Poller<string>;

beforeEach(() => {
handler = jest.fn().mockImplementation((iteration: number) => `polling-${iteration}`);
poller = new Poller<string>(100, 'polling', handler);
});

afterEach(() => {
poller.unsubscribe();
});

it('returns an observable of subject', async () => {
await delay(300);
expect(poller.subject$.getValue()).toBe('polling-2');
});

it('executes a function on an interval', async () => {
await delay(300);
expect(handler).toBeCalledTimes(3);
});

it('no longer polls after unsubscribing', async () => {
await delay(300);
poller.unsubscribe();
await delay(300);
expect(handler).toBeCalledTimes(3);
});

it('does not add next value if returns undefined', async () => {
const values: any[] = [];
const polling = new Poller<string>(100, 'polling', iteration => {
if (iteration % 2 === 0) {
return `polling-${iteration}`;
}
});

polling.subject$.subscribe(value => {
values.push(value);
});
await delay(300);
polling.unsubscribe();

expect(values).toEqual(['polling', 'polling-0', 'polling-2']);
});
});
55 changes: 55 additions & 0 deletions src/core/utils/poller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import { BehaviorSubject, timer } from 'rxjs';

/**
* Create an Observable BehaviorSubject to invoke a function on an interval
* which returns the next value for the observable.
* @public
*/
export class Poller<T> {
/**
* The observable to observe for changes to the poller value.
*/
public readonly subject$ = new BehaviorSubject<T>(this.initialValue);
private poller$ = timer(0, this.frequency);
private subscription = this.poller$.subscribe(async iteration => {
const next = await this.handler(iteration);

if (next !== undefined) {
this.subject$.next(next);
}

return iteration;
});

constructor(
private frequency: number,
private initialValue: T,
private handler: (iteration: number) => Promise<T | undefined> | T | undefined
) {}

/**
* Permanently end the polling operation.
*/
unsubscribe() {
return this.subscription.unsubscribe();
}
}
8 changes: 8 additions & 0 deletions x-pack/plugins/licensing/kibana.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"id": "licensing",
"version": "0.0.1",
"kibanaVersion": "kibana",
"configPath": ["x-pack", "licensing"],
"server": true,
"ui": false
}
115 changes: 115 additions & 0 deletions x-pack/plugins/licensing/server/__fixtures__/setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/*
* 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 { take, skip } from 'rxjs/operators';
import { merge } from 'lodash';
import { ClusterClient } from 'src/core/server';
import { coreMock } from '../../../../../src/core/server/mocks';
import { Plugin } from '../plugin';
import { schema } from '../schema';

export async function licenseMerge(xpackInfo = {}) {
return merge(
{
license: {
uid: '00000000-0000-0000-0000-000000000000',
type: 'basic',
mode: 'basic',
status: 'active',
},
features: {
ccr: {
available: false,
enabled: true,
},
data_frame: {
available: true,
enabled: true,
},
graph: {
available: false,
enabled: true,
},
ilm: {
available: true,
enabled: true,
},
logstash: {
available: false,
enabled: true,
},
ml: {
available: false,
enabled: true,
},
monitoring: {
available: true,
enabled: true,
},
rollup: {
available: true,
enabled: true,
},
security: {
available: true,
enabled: true,
},
sql: {
available: true,
enabled: true,
},
vectors: {
available: true,
enabled: true,
},
voting_only: {
available: true,
enabled: true,
},
watcher: {
available: false,
enabled: true,
},
},
},
xpackInfo
);
}

export async function setupOnly(pluginInitializerContext: any = {}) {
const coreSetup = coreMock.createSetup();
const clusterClient = ((await coreSetup.elasticsearch.dataClient$
.pipe(take(1))
.toPromise()) as unknown) as jest.Mocked<PublicMethodsOf<ClusterClient>>;
const plugin = new Plugin(
coreMock.createPluginInitializerContext({
config: schema.validate(pluginInitializerContext.config || {}),
})
);

return { coreSetup, plugin, clusterClient };
}

export async function setup(xpackInfo = {}, pluginInitializerContext: any = {}) {
const { coreSetup, clusterClient, plugin } = await setupOnly(pluginInitializerContext);

clusterClient.callAsInternalUser.mockResolvedValueOnce(licenseMerge(xpackInfo));

const { license$ } = await plugin.setup(coreSetup);
const license = await license$
.pipe(
skip(1),
take(1)
)
.toPromise();

return {
plugin,
license$,
license,
clusterClient,
};
}
21 changes: 21 additions & 0 deletions x-pack/plugins/licensing/server/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* 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.
*/

export const SERVICE_NAME = 'licensing';
export const DEFAULT_POLLING_FREQUENCY = 30001; // 30 seconds
export enum LICENSE_STATUS {
Unavailable = 'UNAVAILABLE',
Invalid = 'INVALID',
Expired = 'EXPIRED',
Valid = 'VALID',
}
export enum LICENSE_TYPE {
basic = 10,
standard = 20,
gold = 30,
platinum = 40,
trial = 50,
}
13 changes: 13 additions & 0 deletions x-pack/plugins/licensing/server/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 { PluginInitializerContext } from 'src/core/server';
import { schema } from './schema';
import { Plugin } from './plugin';

export * from './types';
export const config = { schema };
export const plugin = (context: PluginInitializerContext) => new Plugin(context);
Loading

0 comments on commit c05b383

Please sign in to comment.