[NP Kibana Migrations ] kibana plugin home (#50444)

* [NP:Kibana:homeAPI] initializes a new plugin (WIP)

* Typing

* New plugin tutorials not needing server working

* Retains legacy tutorial registration and adds new route for new platform tutorial plugin registrations

* Adds comment on where to pre-register general non-plugin specific tutorials

* Converts TutorialsPlugin to TutorialsRegistry service in new Home plugin

* Changes call to location of registerTutorial in registerTutorials

* Adds console log for the home plugin that's returning an empty object

* Removes async from setup and start methods in the home plugin and the tutorials service

* Starts writing tests and creating mocks

* Adds basic tests for TutorialRegistry service

* Adds basic tests for TutorialRegistry service

* Adds test for route

* Adds mocks and tests for the home plugin

* Adds home plugin to security plugin and registers scoped tutorials service

* Removes incorrect addition to src core server

* Fixes type errors

* Deletes unused code

* Deletes duplicate golangMetricsSpecProvider registration

* Nests tutorials service in a tutorials key in the home plugin, changes api http routes for legacy platform and NP

* Changes url variable names
This commit is contained in:
Christiane (Tina) Heiligers 2019-11-18 11:47:27 -07:00 committed by GitHub
parent d04d5e9eef
commit 04425ff6cd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
75 changed files with 866 additions and 126 deletions

View file

@ -21,6 +21,7 @@ import _ from 'lodash';
import { getServices } from './kibana_services';
import { i18n } from '@kbn/i18n';
const baseUrlLP = getServices().addBasePath('/api/kibana/home/tutorials_LP');
const baseUrl = getServices().addBasePath('/api/kibana/home/tutorials');
const headers = new Headers();
headers.append('Accept', 'application/json');
@ -28,22 +29,36 @@ headers.append('Content-Type', 'application/json');
headers.append('kbn-xsrf', 'kibana');
let tutorials = [];
let tutorialsLegacyPlatform = [];
let tutorialsNewPlatform = [];
let tutorialsLoaded = false;
async function loadTutorials() {
try {
const response = await fetch(baseUrl, {
const responseLegacyPlatform = await fetch(baseUrlLP, {
method: 'get',
credentials: 'include',
headers: headers,
});
if (response.status >= 300) {
if (responseLegacyPlatform.status >= 300) {
throw new Error(i18n.translate('kbn.home.loadTutorials.requestFailedErrorMessage', {
defaultMessage: 'Request failed with status code: {status}', values: { status: response.status } }
defaultMessage: 'Request failed with status code: {status}', values: { status: responseLegacyPlatform.status } }
));
}
const responseNewPlatform = await fetch(baseUrl, {
method: 'get',
credentials: 'include',
headers: headers,
});
if (responseNewPlatform.status >= 300) {
throw new Error(i18n.translate('kbn.home.loadTutorials.requestFailedErrorMessage', {
defaultMessage: 'Request failed with status code: {status}', values: { status: responseNewPlatform.status } }
));
}
tutorials = await response.json();
tutorialsLegacyPlatform = await responseLegacyPlatform.json();
tutorialsNewPlatform = await responseNewPlatform.json();
tutorials = tutorialsLegacyPlatform.concat(tutorialsNewPlatform);
tutorialsLoaded = true;
} catch(err) {
getServices().toastNotifications.addDanger({

View file

@ -20,7 +20,7 @@
export function registerTutorials(server) {
server.route({
path: '/api/kibana/home/tutorials',
path: '/api/kibana/home/tutorials_LP',
method: ['GET'],
handler: function (req) {
return server.getTutorials(req);

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/metricbeat_instructions';
export function aerospikeMetricsSpecProvider(server, context) {
export function aerospikeMetricsSpecProvider(context) {
const moduleName = 'aerospike';
return {
id: 'aerospikeMetrics',

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/filebeat_instructions';
export function apacheLogsSpecProvider(server, context) {
export function apacheLogsSpecProvider(context) {
const moduleName = 'apache';
const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'];
return {

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/metricbeat_instructions';
export function apacheMetricsSpecProvider(server, context) {
export function apacheMetricsSpecProvider(context) {
const moduleName = 'apache';
return {
id: 'apacheMetrics',

View file

@ -25,7 +25,7 @@ import {
onPremCloudInstructions,
} from '../../../common/tutorials/auditbeat_instructions';
export function auditbeatSpecProvider(server, context) {
export function auditbeatSpecProvider(context) {
const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'];
return {
id: 'auditbeat',

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/metricbeat_instructions';
export function awsMetricsSpecProvider(server, context) {
export function awsMetricsSpecProvider(context) {
const moduleName = 'aws';
return {
id: 'awsMetrics',

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/metricbeat_instructions';
export function cephMetricsSpecProvider(server, context) {
export function cephMetricsSpecProvider(context) {
const moduleName = 'ceph';
return {
id: 'cephMetrics',

View file

@ -25,7 +25,7 @@ import {
onPremCloudInstructions,
} from '../../../common/tutorials/filebeat_instructions';
export function ciscoLogsSpecProvider(server, context) {
export function ciscoLogsSpecProvider(context) {
const moduleName = 'cisco';
const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'];
return {

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/functionbeat_instructions';
export function cloudwatchLogsSpecProvider(server, context) {
export function cloudwatchLogsSpecProvider(context) {
return {
id: 'cloudwatchLogs',
name: i18n.translate('kbn.server.tutorials.cloudwatchLogs.nameTitle', {

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/metricbeat_instructions';
export function cockroachdbMetricsSpecProvider(server, context) {
export function cockroachdbMetricsSpecProvider(context) {
const moduleName = 'cockroachdb';
return {
id: 'cockroachdbMetrics',

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/metricbeat_instructions';
export function consulMetricsSpecProvider(server, context) {
export function consulMetricsSpecProvider(context) {
const moduleName = 'consul';
return {
id: 'consulMetrics',

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/metricbeat_instructions';
export function corednsMetricsSpecProvider(server, context) {
export function corednsMetricsSpecProvider(context) {
const moduleName = 'coredns';
return {
id: 'corednsMetrics',

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/metricbeat_instructions';
export function couchbaseMetricsSpecProvider(server, context) {
export function couchbaseMetricsSpecProvider(context) {
const moduleName = 'couchbase';
return {
id: 'couchbaseMetrics',

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/metricbeat_instructions';
export function couchdbMetricsSpecProvider(server, context) {
export function couchdbMetricsSpecProvider(context) {
const moduleName = 'couchdb';
return {
id: 'couchdbMetrics',

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/metricbeat_instructions';
export function dockerMetricsSpecProvider(server, context) {
export function dockerMetricsSpecProvider(context) {
const moduleName = 'docker';
return {
id: 'dockerMetrics',

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/metricbeat_instructions';
export function dropwizardMetricsSpecProvider(server, context) {
export function dropwizardMetricsSpecProvider(context) {
const moduleName = 'dropwizard';
return {
id: 'dropwizardMetrics',

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/filebeat_instructions';
export function elasticsearchLogsSpecProvider(server, context) {
export function elasticsearchLogsSpecProvider(context) {
const moduleName = 'elasticsearch';
const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'];
return {

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/metricbeat_instructions';
export function elasticsearchMetricsSpecProvider(server, context) {
export function elasticsearchMetricsSpecProvider(context) {
const moduleName = 'elasticsearch';
return {
id: 'elasticsearchMetrics',

View file

@ -25,7 +25,7 @@ import {
onPremCloudInstructions,
} from '../../../common/tutorials/filebeat_instructions';
export function envoyproxyLogsSpecProvider(server, context) {
export function envoyproxyLogsSpecProvider(context) {
const moduleName = 'envoyproxy';
const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'];
return {

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/metricbeat_instructions';
export function etcdMetricsSpecProvider(server, context) {
export function etcdMetricsSpecProvider(context) {
const moduleName = 'etcd';
return {
id: 'etcdMetrics',

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/metricbeat_instructions';
export function golangMetricsSpecProvider(server, context) {
export function golangMetricsSpecProvider(context) {
const moduleName = 'golang';
return {
id: moduleName + 'Metrics',

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/metricbeat_instructions';
export function haproxyMetricsSpecProvider(server, context) {
export function haproxyMetricsSpecProvider(context) {
const moduleName = 'haproxy';
return {
id: 'haproxyMetrics',

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/filebeat_instructions';
export function iisLogsSpecProvider(server, context) {
export function iisLogsSpecProvider(context) {
const moduleName = 'iis';
const platforms = ['WINDOWS'];
return {

View file

@ -25,7 +25,7 @@ import {
onPremCloudInstructions,
} from '../../../common/tutorials/filebeat_instructions';
export function iptablesLogsSpecProvider(server, context) {
export function iptablesLogsSpecProvider(context) {
const moduleName = 'iptables';
const platforms = ['DEB', 'RPM'];
return {

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/filebeat_instructions';
export function kafkaLogsSpecProvider(server, context) {
export function kafkaLogsSpecProvider(context) {
const moduleName = 'kafka';
const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'];
return {

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/metricbeat_instructions';
export function kafkaMetricsSpecProvider(server, context) {
export function kafkaMetricsSpecProvider(context) {
const moduleName = 'kafka';
return {
id: 'kafkaMetrics',

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/metricbeat_instructions';
export function kibanaMetricsSpecProvider(server, context) {
export function kibanaMetricsSpecProvider(context) {
const moduleName = 'kibana';
return {
id: 'kibanaMetrics',

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/metricbeat_instructions';
export function kubernetesMetricsSpecProvider(server, context) {
export function kubernetesMetricsSpecProvider(context) {
const moduleName = 'kubernetes';
return {
id: 'kubernetesMetrics',

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/filebeat_instructions';
export function logstashLogsSpecProvider(server, context) {
export function logstashLogsSpecProvider(context) {
const moduleName = 'logstash';
const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'];
return {

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/metricbeat_instructions';
export function logstashMetricsSpecProvider(server, context) {
export function logstashMetricsSpecProvider(context) {
const moduleName = 'logstash';
return {
id: moduleName + 'Metrics',

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/metricbeat_instructions';
export function memcachedMetricsSpecProvider(server, context) {
export function memcachedMetricsSpecProvider(context) {
const moduleName = 'memcached';
return {
id: 'memcachedMetrics',

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/metricbeat_instructions';
export function mongodbMetricsSpecProvider(server, context) {
export function mongodbMetricsSpecProvider(context) {
const moduleName = 'mongodb';
return {
id: 'mongodbMetrics',

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/metricbeat_instructions';
export function mssqlMetricsSpecProvider(server, context) {
export function mssqlMetricsSpecProvider(context) {
const moduleName = 'mssql';
return {
id: 'mssqlMetrics',

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/metricbeat_instructions';
export function muninMetricsSpecProvider(server, context) {
export function muninMetricsSpecProvider(context) {
const moduleName = 'munin';
return {
id: 'muninMetrics',

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/filebeat_instructions';
export function mysqlLogsSpecProvider(server, context) {
export function mysqlLogsSpecProvider(context) {
const moduleName = 'mysql';
const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'];
return {

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/metricbeat_instructions';
export function mysqlMetricsSpecProvider(server, context) {
export function mysqlMetricsSpecProvider(context) {
const moduleName = 'mysql';
return {
id: 'mysqlMetrics',

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/filebeat_instructions';
export function natsLogsSpecProvider(server, context) {
export function natsLogsSpecProvider(context) {
const moduleName = 'nats';
const geoipRequired = false;
const uaRequired = false;

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/metricbeat_instructions';
export function natsMetricsSpecProvider(server, context) {
export function natsMetricsSpecProvider(context) {
const moduleName = 'nats';
return {
id: 'natsMetrics',

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/filebeat_instructions';
export function nginxLogsSpecProvider(server, context) {
export function nginxLogsSpecProvider(context) {
const moduleName = 'nginx';
const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'];
return {

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/metricbeat_instructions';
export function nginxMetricsSpecProvider(server, context) {
export function nginxMetricsSpecProvider(context) {
const moduleName = 'nginx';
return {
id: 'nginxMetrics',

View file

@ -25,7 +25,7 @@ import {
onPremCloudInstructions,
} from '../../../common/tutorials/filebeat_instructions';
export function osqueryLogsSpecProvider(server, context) {
export function osqueryLogsSpecProvider(context) {
const moduleName = 'osquery';
const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'];
return {

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/metricbeat_instructions';
export function phpfpmMetricsSpecProvider(server, context) {
export function phpfpmMetricsSpecProvider(context) {
const moduleName = 'php_fpm';
return {
id: 'phpfpmMetrics',

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/filebeat_instructions';
export function postgresqlLogsSpecProvider(server, context) {
export function postgresqlLogsSpecProvider(context) {
const moduleName = 'postgresql';
const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'];
return {

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/metricbeat_instructions';
export function postgresqlMetricsSpecProvider(server, context) {
export function postgresqlMetricsSpecProvider(context) {
const moduleName = 'postgresql';
return {
id: 'postgresqlMetrics',

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/metricbeat_instructions';
export function prometheusMetricsSpecProvider(server, context) {
export function prometheusMetricsSpecProvider(context) {
const moduleName = 'prometheus';
return {
id: moduleName + 'Metrics',

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/metricbeat_instructions';
export function rabbitmqMetricsSpecProvider(server, context) {
export function rabbitmqMetricsSpecProvider(context) {
const moduleName = 'rabbitmq';
return {
id: 'rabbitmqMetrics',

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/filebeat_instructions';
export function redisLogsSpecProvider(server, context) {
export function redisLogsSpecProvider(context) {
const moduleName = 'redis';
const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'];
return {

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/metricbeat_instructions';
export function redisMetricsSpecProvider(server, context) {
export function redisMetricsSpecProvider(context) {
const moduleName = 'redis';
return {
id: 'redisMetrics',

View file

@ -16,7 +16,6 @@
* specific language governing permissions and limitations
* under the License.
*/
import { systemLogsSpecProvider } from './system_logs';
import { systemMetricsSpecProvider } from './system_metrics';
import { apacheLogsSpecProvider } from './apache_logs';
@ -81,66 +80,66 @@ import { consulMetricsSpecProvider } from './consul_metrics';
import { cockroachdbMetricsSpecProvider } from './cockroachdb_metrics';
export function registerTutorials(server) {
server.registerTutorial(systemLogsSpecProvider);
server.registerTutorial(systemMetricsSpecProvider);
server.registerTutorial(apacheLogsSpecProvider);
server.registerTutorial(apacheMetricsSpecProvider);
server.registerTutorial(elasticsearchLogsSpecProvider);
server.registerTutorial(iisLogsSpecProvider);
server.registerTutorial(kafkaLogsSpecProvider);
server.registerTutorial(logstashLogsSpecProvider);
server.registerTutorial(nginxLogsSpecProvider);
server.registerTutorial(nginxMetricsSpecProvider);
server.registerTutorial(mysqlLogsSpecProvider);
server.registerTutorial(mysqlMetricsSpecProvider);
server.registerTutorial(mongodbMetricsSpecProvider);
server.registerTutorial(osqueryLogsSpecProvider);
server.registerTutorial(phpfpmMetricsSpecProvider);
server.registerTutorial(postgresqlMetricsSpecProvider);
server.registerTutorial(postgresqlLogsSpecProvider);
server.registerTutorial(rabbitmqMetricsSpecProvider);
server.registerTutorial(redisLogsSpecProvider);
server.registerTutorial(redisMetricsSpecProvider);
server.registerTutorial(suricataLogsSpecProvider);
server.registerTutorial(dockerMetricsSpecProvider);
server.registerTutorial(kubernetesMetricsSpecProvider);
server.registerTutorial(uwsgiMetricsSpecProvider);
server.registerTutorial(netflowSpecProvider);
server.registerTutorial(traefikLogsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(systemLogsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(systemMetricsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(apacheLogsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(apacheMetricsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(elasticsearchLogsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(iisLogsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(kafkaLogsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(logstashLogsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(nginxLogsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(nginxMetricsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(mysqlLogsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(mysqlMetricsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(mongodbMetricsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(osqueryLogsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(phpfpmMetricsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(postgresqlMetricsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(postgresqlLogsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(rabbitmqMetricsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(redisLogsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(redisMetricsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(suricataLogsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(dockerMetricsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(kubernetesMetricsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(uwsgiMetricsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(netflowSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(traefikLogsSpecProvider);
server.registerTutorial(apmSpecProvider);
server.registerTutorial(cephMetricsSpecProvider);
server.registerTutorial(aerospikeMetricsSpecProvider);
server.registerTutorial(couchbaseMetricsSpecProvider);
server.registerTutorial(dropwizardMetricsSpecProvider);
server.registerTutorial(elasticsearchMetricsSpecProvider);
server.registerTutorial(etcdMetricsSpecProvider);
server.registerTutorial(haproxyMetricsSpecProvider);
server.registerTutorial(kafkaMetricsSpecProvider);
server.registerTutorial(kibanaMetricsSpecProvider);
server.registerTutorial(memcachedMetricsSpecProvider);
server.registerTutorial(muninMetricsSpecProvider);
server.registerTutorial(vSphereMetricsSpecProvider);
server.registerTutorial(windowsMetricsSpecProvider);
server.registerTutorial(windowsEventLogsSpecProvider);
server.registerTutorial(golangMetricsSpecProvider);
server.registerTutorial(logstashMetricsSpecProvider);
server.registerTutorial(prometheusMetricsSpecProvider);
server.registerTutorial(zookeeperMetricsSpecProvider);
server.registerTutorial(uptimeMonitorsSpecProvider);
server.registerTutorial(cloudwatchLogsSpecProvider);
server.registerTutorial(awsMetricsSpecProvider);
server.registerTutorial(mssqlMetricsSpecProvider);
server.registerTutorial(natsMetricsSpecProvider);
server.registerTutorial(natsLogsSpecProvider);
server.registerTutorial(zeekLogsSpecProvider);
server.registerTutorial(corednsMetricsSpecProvider);
server.registerTutorial(corednsLogsSpecProvider);
server.registerTutorial(auditbeatSpecProvider);
server.registerTutorial(iptablesLogsSpecProvider);
server.registerTutorial(ciscoLogsSpecProvider);
server.registerTutorial(envoyproxyLogsSpecProvider);
server.registerTutorial(couchdbMetricsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(cephMetricsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(aerospikeMetricsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(couchbaseMetricsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(dropwizardMetricsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(elasticsearchMetricsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(etcdMetricsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(haproxyMetricsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(kafkaMetricsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(kibanaMetricsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(memcachedMetricsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(muninMetricsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(vSphereMetricsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(windowsMetricsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(windowsEventLogsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(golangMetricsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(logstashMetricsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(prometheusMetricsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(zookeeperMetricsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(uptimeMonitorsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(cloudwatchLogsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(awsMetricsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(mssqlMetricsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(natsMetricsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(natsLogsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(zeekLogsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(corednsMetricsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(corednsLogsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(auditbeatSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(iptablesLogsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(ciscoLogsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(envoyproxyLogsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(couchdbMetricsSpecProvider);
server.registerTutorial(emsBoundariesSpecProvider);
server.registerTutorial(consulMetricsSpecProvider);
server.registerTutorial(cockroachdbMetricsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(consulMetricsSpecProvider);
server.newPlatform.setup.plugins.home.tutorials.registerTutorial(cockroachdbMetricsSpecProvider);
}

View file

@ -25,7 +25,7 @@ import {
onPremCloudInstructions,
} from '../../../common/tutorials/filebeat_instructions';
export function suricataLogsSpecProvider(server, context) {
export function suricataLogsSpecProvider(context) {
const moduleName = 'suricata';
const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'];
return {

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/filebeat_instructions';
export function systemLogsSpecProvider(server, context) {
export function systemLogsSpecProvider(context) {
const moduleName = 'system';
const platforms = ['OSX', 'DEB', 'RPM'];
return {

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/metricbeat_instructions';
export function systemMetricsSpecProvider(server, context) {
export function systemMetricsSpecProvider(context) {
const moduleName = 'system';
return {
id: 'systemMetrics',

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/filebeat_instructions';
export function traefikLogsSpecProvider(server, context) {
export function traefikLogsSpecProvider(context) {
const moduleName = 'traefik';
const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'];
return {

View file

@ -25,7 +25,7 @@ import {
onPremCloudInstructions,
} from '../../../common/tutorials/heartbeat_instructions';
export function uptimeMonitorsSpecProvider(server, context) {
export function uptimeMonitorsSpecProvider(context) {
return {
id: 'uptimeMonitors',
name: i18n.translate('kbn.server.tutorials.uptimeMonitors.nameTitle', {

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/metricbeat_instructions';
export function uwsgiMetricsSpecProvider(server, context) {
export function uwsgiMetricsSpecProvider(context) {
const moduleName = 'uwsgi';
return {
id: 'uwsgiMetrics',

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/metricbeat_instructions';
export function vSphereMetricsSpecProvider(server, context) {
export function vSphereMetricsSpecProvider(context) {
const moduleName = 'vsphere';
return {
id: 'vsphereMetrics',

View file

@ -25,7 +25,7 @@ import {
onPremCloudInstructions,
} from '../../../common/tutorials/winlogbeat_instructions';
export function windowsEventLogsSpecProvider(server, context) {
export function windowsEventLogsSpecProvider(context) {
return {
id: 'windowsEventLogs',
name: i18n.translate('kbn.server.tutorials.windowsEventLogs.nameTitle', {

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/metricbeat_instructions';
export function windowsMetricsSpecProvider(server, context) {
export function windowsMetricsSpecProvider(context) {
const moduleName = 'windows';
return {
id: 'windowsMetrics',

View file

@ -25,7 +25,7 @@ import {
onPremCloudInstructions,
} from '../../../common/tutorials/filebeat_instructions';
export function zeekLogsSpecProvider(server, context) {
export function zeekLogsSpecProvider(context) {
const moduleName = 'zeek';
const platforms = ['OSX', 'DEB', 'RPM'];
return {

View file

@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/metricbeat_instructions';
export function zookeeperMetricsSpecProvider(server, context) {
export function zookeeperMetricsSpecProvider(context) {
const moduleName = 'zookeeper';
return {
id: moduleName + 'Metrics',

View file

@ -36,6 +36,7 @@ export function tutorialsMixin(kbnServer, server) {
});
server.decorate('server', 'registerTutorial', (specProvider) => {
// registration during setup
const emptyContext = {};
const { error } = Joi.validate(specProvider(server, emptyContext), tutorialSchema);
@ -47,6 +48,7 @@ export function tutorialsMixin(kbnServer, server) {
});
server.decorate('server', 'addScopedTutorialContextFactory', (scopedTutorialContextFactory) => {
// returned by the setup method of the new plugin, they will do the same thing as now
if (typeof scopedTutorialContextFactory !== 'function') {
throw new Error(`Unable to add scoped(request) context factory because you did not provide a function`);
}

View file

@ -0,0 +1,6 @@
{
"id": "home",
"version": "kibana",
"server": true,
"ui": false
}

View file

@ -0,0 +1,24 @@
/*
* 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.
*/
export { HomePluginSetup, HomePluginStart } from './plugin';
export { TutorialProvider } from './services';
import { HomePlugin } from './plugin';
export const plugin = () => new HomePlugin();

View file

@ -0,0 +1,149 @@
/*
* 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 Joi from 'joi';
const PARAM_TYPES = {
NUMBER: 'number',
STRING: 'string',
};
const TUTORIAL_CATEGORY = {
LOGGING: 'logging',
SIEM: 'siem',
METRICS: 'metrics',
OTHER: 'other',
};
const dashboardSchema = Joi.object({
id: Joi.string().required(), // Dashboard saved object id
linkLabel: Joi.string().when('isOverview', {
is: true,
then: Joi.required(),
}),
// Is this an Overview / Entry Point dashboard?
isOverview: Joi.boolean().required(),
});
const artifactsSchema = Joi.object({
// Fields present in Elasticsearch documents created by this product.
exportedFields: Joi.object({
documentationUrl: Joi.string().required(),
}),
// Kibana dashboards created by this product.
dashboards: Joi.array()
.items(dashboardSchema)
.required(),
application: Joi.object({
path: Joi.string().required(),
label: Joi.string().required(),
}),
});
const statusCheckSchema = Joi.object({
title: Joi.string(),
text: Joi.string(),
btnLabel: Joi.string(),
success: Joi.string(),
error: Joi.string(),
esHitsCheck: Joi.object({
index: Joi.alternatives()
.try(Joi.string(), Joi.array().items(Joi.string()))
.required(),
query: Joi.object().required(),
}).required(),
});
const instructionSchema = Joi.object({
title: Joi.string(),
textPre: Joi.string(),
commands: Joi.array().items(Joi.string().allow('')),
textPost: Joi.string(),
});
const instructionVariantSchema = Joi.object({
id: Joi.string().required(),
instructions: Joi.array()
.items(instructionSchema)
.required(),
});
const instructionSetSchema = Joi.object({
title: Joi.string(),
callOut: Joi.object({
title: Joi.string().required(),
message: Joi.string(),
iconType: Joi.string(),
}),
// Variants (OSes, languages, etc.) for which tutorial instructions are specified.
instructionVariants: Joi.array()
.items(instructionVariantSchema)
.required(),
statusCheck: statusCheckSchema,
});
const paramSchema = Joi.object({
defaultValue: Joi.required(),
id: Joi.string()
.regex(/^[a-zA-Z_]+$/)
.required(),
label: Joi.string().required(),
type: Joi.string()
.valid(Object.values(PARAM_TYPES))
.required(),
});
const instructionsSchema = Joi.object({
instructionSets: Joi.array()
.items(instructionSetSchema)
.required(),
params: Joi.array().items(paramSchema),
});
export const tutorialSchema = {
id: Joi.string()
.regex(/^[a-zA-Z0-9-]+$/)
.required(),
category: Joi.string()
.valid(Object.values(TUTORIAL_CATEGORY))
.required(),
name: Joi.string().required(),
isBeta: Joi.boolean().default(false),
shortDescription: Joi.string().required(),
euiIconType: Joi.string(), // EUI icon type string, one of https://elastic.github.io/eui/#/icons
longDescription: Joi.string().required(),
completionTimeMinutes: Joi.number().integer(),
previewImagePath: Joi.string(),
// kibana and elastic cluster running on prem
onPrem: instructionsSchema.required(),
// kibana and elastic cluster running in elastic's cloud
elasticCloud: instructionsSchema,
// kibana running on prem and elastic cluster running in elastic's cloud
onPremElasticCloud: instructionsSchema,
// Elastic stack artifacts produced by product when it is setup and run.
artifacts: artifactsSchema,
// saved objects used by data module.
savedObjects: Joi.array().items(),
savedObjectsInstallMsg: Joi.string(),
};

View file

@ -0,0 +1,110 @@
/*
* 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 { IconType } from '@elastic/eui';
import { KibanaRequest } from 'src/core/server';
/** @public */
export enum TutorialsCategory {
LOGGING = 'logging',
SIEM = 'siem',
METRICS = 'metrics',
OTHER = 'other',
}
export interface ParamTypes {
NUMBER: string;
STRING: string;
}
export interface InstructionSetSchema {
readonly title: string;
readonly callOut: {
title: string;
message: string;
iconType: IconType;
};
}
export interface ParamsSchema {
defaultValue: any;
id: string;
label: string;
type: ParamTypes;
}
export interface InstructionsSchema {
readonly instructionSets: InstructionSetSchema[];
readonly params: ParamsSchema[];
}
export interface DashboardSchema {
id: string;
linkLabel?: {
is: boolean;
then: any;
};
isOverview: boolean;
}
export interface ArtifactsSchema {
readonly exportedFields: {
documentationUrl: string;
};
readonly dashboards: DashboardSchema[];
readonly application: {
path: string;
label: string;
};
}
export interface TutorialSchema {
id: string;
category: TutorialsCategory;
name: string;
isBeta: boolean;
shortDescription: string;
euiIconType: IconType; // EUI icon type string, one of https://elastic.github.io/eui/#/icon;
longDescription: string;
completionTimeMinutes: number;
previewImagePath: string;
// kibana and elastic cluster running on prem
onPrem: InstructionsSchema;
// kibana and elastic cluster running in elastic's cloud
elasticCloud: InstructionsSchema;
// kibana running on prem and elastic cluster running in elastic's cloud
onPremElasticCloud: InstructionsSchema;
// Elastic stack artifacts produced by product when it is setup and run.
artifacts: ArtifactsSchema;
// saved objects used by data module.
savedObjects: any[];
savedObjectsInstallMsg: string;
}
export type TutorialProvider = (context: { [key: string]: unknown }) => TutorialSchema;
export type TutorialContextFactory = (
req: KibanaRequest<
Readonly<{
[x: string]: any;
}>,
Readonly<{
[x: string]: any;
}>,
Readonly<{
[x: string]: any;
}>
>
) => { [key: string]: unknown };
export type ScopedTutorialContextFactory = (...args: any[]) => any;

View file

@ -0,0 +1,24 @@
/*
* 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 { tutorialsRegistryMock } from './services/tutorials_registry.mock';
export const registryMock = tutorialsRegistryMock.create();
jest.doMock('./services', () => ({
TutorialsRegistry: jest.fn(() => registryMock),
}));

View file

@ -0,0 +1,51 @@
/*
* 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 { registryMock } from './plugin.test.mocks';
import { HomePlugin } from './plugin';
import { coreMock } from '../../../core/server/mocks';
import { CoreSetup } from '../../../core/server';
type MockedKeys<T> = { [P in keyof T]: jest.Mocked<T[P]> };
describe('HomePlugin', () => {
beforeEach(() => {
registryMock.setup.mockClear();
registryMock.start.mockClear();
});
describe('setup', () => {
const mockCoreSetup: MockedKeys<CoreSetup> = coreMock.createSetup();
test('wires up and returns registerTutorial and addScopedTutorialContextFactory', () => {
const setup = new HomePlugin().setup(mockCoreSetup);
expect(setup).toHaveProperty('tutorials');
expect(setup.tutorials).toHaveProperty('registerTutorial');
expect(setup.tutorials).toHaveProperty('addScopedTutorialContextFactory');
});
});
describe('start', () => {
test('is defined', () => {
const start = new HomePlugin().start();
expect(start).toBeDefined();
expect(start).toHaveProperty('tutorials');
});
});
});

View file

@ -0,0 +1,46 @@
/*
* 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 { CoreSetup, Plugin } from 'src/core/server';
import { TutorialsRegistry, TutorialsRegistrySetup, TutorialsRegistryStart } from './services';
export class HomePlugin implements Plugin<HomePluginSetup, HomePluginStart> {
private readonly tutorialsRegistry = new TutorialsRegistry();
public setup(core: CoreSetup) {
return {
tutorials: { ...this.tutorialsRegistry.setup(core) },
};
}
public start() {
return {
tutorials: { ...this.tutorialsRegistry.start() },
};
}
}
/** @public */
export interface HomePluginSetup {
tutorials: TutorialsRegistrySetup;
}
/** @public */
export interface HomePluginStart {
tutorials: TutorialsRegistryStart;
}

View file

@ -0,0 +1,27 @@
/*
* 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.
*/
// provided to other plugins as APIs
// should model the plugin lifecycle
export {
TutorialsRegistry,
TutorialsRegistrySetup,
TutorialsRegistryStart,
} from './tutorials_registry';
export * from '../lib/tutorials_registry_types';

View file

@ -0,0 +1,53 @@
/*
* 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 {
TutorialsRegistrySetup,
TutorialsRegistryStart,
TutorialsRegistry,
} from './tutorials_registry';
const createSetupMock = (): jest.Mocked<TutorialsRegistrySetup> => {
const setup = {
registerTutorial: jest.fn(),
addScopedTutorialContextFactory: jest.fn(),
};
return setup;
};
const createStartMock = (): jest.Mocked<TutorialsRegistryStart> => {
const start = {};
return start;
};
const createMock = (): jest.Mocked<PublicMethodsOf<TutorialsRegistry>> => {
const service = {
setup: jest.fn(),
start: jest.fn(),
};
service.setup.mockImplementation(createSetupMock);
service.start.mockImplementation(createStartMock);
return service;
};
export const tutorialsRegistryMock = {
createSetup: createSetupMock,
createStart: createStartMock,
create: createMock,
};

View file

@ -0,0 +1,139 @@
/*
* 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 { TutorialsRegistry } from './tutorials_registry';
import { coreMock } from '../../../../core/server/mocks';
import { CoreSetup } from '../../../../core/server';
import { httpServerMock } from '../../../../../src/core/server/mocks';
import {
TutorialProvider,
TutorialSchema,
TutorialsCategory,
ScopedTutorialContextFactory,
} from '../lib/tutorials_registry_types';
const INVALID_TUTORIAL: TutorialSchema = {
id: 'test',
category: 'logging' as TutorialsCategory,
name: '',
isBeta: false,
shortDescription: 'short description',
euiIconType: 'alert',
longDescription: 'long description with lots of text',
completionTimeMinutes: 10,
previewImagePath: 'path',
onPrem: { instructionSets: [], params: [] },
elasticCloud: { instructionSets: [], params: [] },
onPremElasticCloud: { instructionSets: [], params: [] },
artifacts: {
exportedFields: { documentationUrl: 'url' },
dashboards: [],
application: { path: 'path', label: 'path' },
},
savedObjects: [],
savedObjectsInstallMsg: 'testMsg',
};
const VALID_TUTORIAL: TutorialSchema = {
id: 'test',
category: 'logging' as TutorialsCategory,
name: 'new tutorial provider',
isBeta: false,
shortDescription: 'short description',
euiIconType: 'alert',
longDescription: 'long description with lots of text',
completionTimeMinutes: 10,
previewImagePath: 'path',
onPrem: { instructionSets: [], params: [] },
elasticCloud: { instructionSets: [], params: [] },
onPremElasticCloud: { instructionSets: [], params: [] },
artifacts: {
exportedFields: { documentationUrl: 'url' },
dashboards: [],
application: { path: 'path', label: 'path' },
},
savedObjects: [],
savedObjectsInstallMsg: 'testMsg',
};
const invalidTutorialProvider = INVALID_TUTORIAL;
const validTutorialProvider = VALID_TUTORIAL;
describe('TutorialsRegistry', () => {
let mockCoreSetup: MockedKeys<CoreSetup>;
let testProvider: TutorialProvider;
let testScopedTutorialContextFactory: ScopedTutorialContextFactory;
describe('GET /api/kibana/home/tutorials', () => {
beforeEach(() => {
mockCoreSetup = coreMock.createSetup();
});
test('has a router that retrieves registered tutorials', () => {
const mockResponse = httpServerMock.createResponseFactory();
expect(mockResponse.ok.mock.calls).toMatchInlineSnapshot(`Array []`);
});
});
describe('setup', () => {
test('exposes proper contract', () => {
const setup = new TutorialsRegistry().setup(mockCoreSetup);
expect(setup).toHaveProperty('registerTutorial');
expect(setup).toHaveProperty('addScopedTutorialContextFactory');
});
test('registerTutorial throws when registering a tutorial with an invalid schema', () => {
const setup = new TutorialsRegistry().setup(mockCoreSetup);
testProvider = ({}) => invalidTutorialProvider;
expect(() => setup.registerTutorial(testProvider)).toThrowErrorMatchingInlineSnapshot(
`"Unable to register tutorial spec because its invalid. ValidationError: child \\"name\\" fails because [\\"name\\" is not allowed to be empty]"`
);
});
test('registerTutorial registers a tutorial with a valid schema', () => {
const setup = new TutorialsRegistry().setup(mockCoreSetup);
testProvider = ({}) => validTutorialProvider;
expect(() => setup.registerTutorial(testProvider)).not.toThrowError();
});
test('addScopedTutorialContextFactory throws when given a scopedTutorialContextFactory that is not a function', () => {
const setup = new TutorialsRegistry().setup(mockCoreSetup);
const testItem = {} as TutorialProvider;
expect(() =>
setup.addScopedTutorialContextFactory(testItem)
).toThrowErrorMatchingInlineSnapshot(
`"Unable to add scoped(request) context factory because you did not provide a function"`
);
});
test('addScopedTutorialContextFactory adds a scopedTutorialContextFactory when given a function', () => {
const setup = new TutorialsRegistry().setup(mockCoreSetup);
testScopedTutorialContextFactory = ({}) => 'string';
expect(() =>
setup.addScopedTutorialContextFactory(testScopedTutorialContextFactory)
).not.toThrowError();
});
});
describe('start', () => {
test('exposes proper contract', () => {
const start = new TutorialsRegistry().start();
expect(start).toBeDefined();
});
});
});

View file

@ -0,0 +1,88 @@
/*
* 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 Joi from 'joi';
import { CoreSetup } from 'src/core/server';
import {
TutorialProvider,
TutorialContextFactory,
ScopedTutorialContextFactory,
} from '../lib/tutorials_registry_types';
import { tutorialSchema } from '../lib/tutorial_schema';
export class TutorialsRegistry {
private readonly tutorialProviders: TutorialProvider[] = []; // pre-register all the tutorials we know we want in here
private readonly scopedTutorialContextFactories: TutorialContextFactory[] = [];
public setup(core: CoreSetup) {
const router = core.http.createRouter();
router.get(
{ path: '/api/kibana/home/tutorials', validate: false },
async (context, req, res) => {
const initialContext = {};
const scopedContext = this.scopedTutorialContextFactories.reduce(
(accumulatedContext, contextFactory) => {
return { ...accumulatedContext, ...contextFactory(req) };
},
initialContext
);
return res.ok({
body: this.tutorialProviders.map(tutorialProvider => {
return tutorialProvider(scopedContext); // All the tutorialProviders need to be refactored so that they don't need the server.
}),
});
}
);
return {
registerTutorial: (specProvider: TutorialProvider) => {
const emptyContext = {};
const { error } = Joi.validate(specProvider(emptyContext), tutorialSchema);
if (error) {
throw new Error(`Unable to register tutorial spec because its invalid. ${error}`);
}
this.tutorialProviders.push(specProvider);
},
addScopedTutorialContextFactory: (
scopedTutorialContextFactory: ScopedTutorialContextFactory
) => {
if (typeof scopedTutorialContextFactory !== 'function') {
throw new Error(
`Unable to add scoped(request) context factory because you did not provide a function`
);
}
this.scopedTutorialContextFactories.push(scopedTutorialContextFactory);
},
};
}
public start() {
return {};
}
}
/** @public */
export type TutorialsRegistrySetup = ReturnType<TutorialsRegistry['setup']>;
/** @public */
export type TutorialsRegistryStart = ReturnType<TutorialsRegistry['start']>;

View file

@ -4,7 +4,7 @@
"kibanaVersion": "kibana",
"configPath": ["xpack", "spaces"],
"requiredPlugins": ["features", "licensing"],
"optionalPlugins": ["security"],
"optionalPlugins": ["security", "home"],
"server": true,
"ui": false
}

View file

@ -31,7 +31,7 @@ import { ConfigType } from './config';
import { toggleUICapabilities } from './lib/toggle_ui_capabilities';
import { initSpacesRequestInterceptors } from './lib/request_interceptors';
import { initExternalSpacesApi } from './routes/api/external';
import { HomePluginSetup } from '../../../../src/plugins/home/server';
/**
* Describes a set of APIs that is available in the legacy platform only and required by this plugin
* to function properly.
@ -62,6 +62,7 @@ export interface PluginsSetup {
features: FeaturesPluginSetup;
licensing: LicensingPluginSetup;
security?: SecurityPluginSetup;
home?: HomePluginSetup;
}
export interface SpacesPluginSetup {
@ -138,6 +139,12 @@ export class Plugin {
plugins.security.registerSpacesService(spacesService);
}
if (plugins.home) {
plugins.home.tutorials.addScopedTutorialContextFactory(
createSpacesTutorialContextFactory(spacesService)
);
}
return {
spacesService,
__legacyCompat: {