[6.x] Kibana Home page - phase two (#14749) (#15965)

* Kibana Home page - phase two (#14749)

* add tutorial directory and home promo section

* tutorial components

* use KuiCodeEditor for displaying instruction code

* move spec files to server so joi can be used. Fetch via rest API

* Adding more tutorials (#4)

* More edits on the Apache logs tutorial

* Added nginx, mysql, and sytem modules for FB

* Moved apache to apacheLogs and added an apacheMetrics tutorial

* Added mysqlMetrics, nginxMetrics, systemMetrics tutorials

* Reduce duplication in the tutorials

This uses common objects for the install and start steps for Filebeat.
Same can be done for MB.

* fix windows path for config file

* add markdown parsing

* use mustache to replace config.kibana.version with kibana version

* add image preview to tutorial introduction

* fix css class name

* add param types constants

* add docs variables

* [WIP] Logstash Netflow module tutorial (#5)

* First draft of Logstash Netflow module tutorial

* Incorporated writing style suggestions

* pass params to template replace logic

* parameter inputs

* use isReadOnly flag from ui-framework for KuiCodeEditor

* dedemorton commits on netflow

* remove trailing slash from base links

* add config.docs.logstash and fix vertical spacing between Content component and commands

* Use logstash docs config variable

* Starting to add Deb instructions

* Fix Logstash documentation link

* Make commands optional

* Refactor: extract common LS instructions

* Edits for the existing tutorials

* change schema to support three instruction types

* [Netflow tutorial] Simplify OSX instructions

* replace axios with fetch

* pass credentials to tutorial fetch

* display cloud instructions when cloud set

* RadioButtonGroup component

* update copy

* add tutorial component jest tests

* content component test

* load isCloudEnabled in home_app

* add functional test ensuring add data tutorials are fetch and displayed

* rename card btns to 'Add data', fix type in tutorial directory tab, remove 'Set up index pattern from tutorial directory'

* move parameters form to right of instruction set title

* add copy snippet button, remove line numbers from command block

* add breadcrumb to tutorial view

* update tutorial jest snapshot

* use componentDidMount and ignore async results if componenent has been unmounted

* define shape of prop for instructionVariants and params. Create NumberParameter and StringParameter components

* add bread crumb to add data directory page

* Add cloud version of the apache_logs tutorial (#16)

* Add cloud version of the apache_logs tutorial

* Added onprem-cloud version as well

* fix styling broken by EUI rebase

* add artifacts to tutorial schema

* fix styling for code block

* [Tutorials] Netflow: instructions for onPremCloud (#18)

* Extract common on-prem cloud instructions so LS and Beats can share them

* Extracting common instructions; adding onPremCloud instructions

* fix copy bug where copy would only contain previously selected text

* make string parameter input type be text

* Implementing Elastic Cloud tutorial for Netflow module (#19)

* More tutorial edits (#20)

* More tutorial edits

This updates the on prem instructions with a step that installs the GeoIP and
UA plugins in ES. It also makes the on-prem steps more consistent with the cloud
instructions which results in less redundancy in the code.

* Show config step for all variants

* More DRY in the tutorial content

* Updated screenshot for apache_logs

* wrap markdown content in markdown-body class

* use EuiFlexGroup to remove wasted space with 'copy snippet' button and instruction text

* change OSX to macOS, use Computed property names for instruction_variant DISPLAY_MAP, replace /app/kibana with kbnBaseUrl, remove unneeded if check in copy_to_clippboard, put getTutorials mixin on server instead of request

* capitilize 'C' in Elastic Cloud

* remove try/catch from copy_to_clipboard

* Removing unrelated instructions

* Copy editing fixes

* Multiply edits to the Beats tutorials (#21)

* Updated Nginx module

* Updated MySQL logs module

* Updated system logs module

* Correct the on_prem_cloud enable steps

* Updated the Nginx metrics tutorial and added screenshot

* Updated the Apache metrics module + screenshot

* Updated the MySQL metrics module + screenshot

* Updated the system metrics module + screenshot

* prevent 'Copy snippet' button text from wrapping

* [Netflow tutorial] Windows instructions (#22)

* [Netflow tutorial] Adding onPrem instructions for Windows

* Removing unrelated/superfluous instructions

* Adding Windows instructions for onPremElasticCloud and elasticCloud

* use EuiImage so tutorial images are clickable to view in full screen

* fix jest tests

* set fullScreenIconColor and alt options for EuiImage, add space between command block and instruction text

* fix broken depenencies (#15960)

* update yarn.lock
This commit is contained in:
Nathan Reese 2018-01-10 11:40:06 -07:00 committed by GitHub
parent 1dea44c592
commit ff460a70cc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
106 changed files with 4233 additions and 8 deletions

View file

@ -156,6 +156,7 @@
"moment": "2.13.0",
"moment-timezone": "0.5.4",
"ngreact": "0.5.1",
"mustache": "2.3.0",
"no-ui-slider": "1.2.0",
"node-fetch": "1.3.2",
"pegjs": "0.9.0",

View file

@ -0,0 +1,40 @@
export const FILEBEAT_CLOUD_INSTRUCTIONS = {
CONFIG: {
OSX: {
title: 'Edit the configuration',
textPre: 'Modify `filebeat.yml` to set the connection information for Elastic Cloud:',
commands: [
'cloud.id: "{config.cloud.id}"',
'cloud.auth: "elastic:<password>"'
],
textPost: 'Where `<password>` is the password of the `elastic` user.'
},
DEB: {
title: 'Edit the configuration',
textPre: 'Modify `/etc/filebeat/filebeat.yml` to set the connection information for Elastic Cloud:',
commands: [
'cloud.id: "{config.cloud.id}"',
'cloud.auth: "elastic:<password>"'
],
textPost: 'Where `<password>` is the password of the `elastic` user.'
},
RPM: {
title: 'Edit the configuration',
textPre: 'Modify `/etc/filebeat/filebeat.yml` to set the connection information for Elastic Cloud:',
commands: [
'cloud.id: "{config.cloud.id}"',
'cloud.auth: "elastic:<password>"'
],
textPost: 'Where `<password>` is the password of the `elastic` user.'
},
WINDOWS: {
title: 'Edit the configuration',
textPre: 'Modify `C:\\Program Files\\Filebeat\\filebeat.yml` to set the connection information for Elastic Cloud:',
commands: [
'cloud.id: "{config.cloud.id}"',
'cloud.auth: "elastic:<password>"'
],
textPost: 'Where `<password>` is the password of the `elastic` user.'
}
}
};

View file

@ -0,0 +1,166 @@
export const FILEBEAT_INSTRUCTIONS = {
INSTALL: {
OSX: {
title: 'Download and install Filebeat',
textPre: 'First time using Filebeat? See the [Getting Started Guide]' +
'({config.docs.beats.filebeat}/filebeat-getting-started.html).',
commands: [
'curl -L -O https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-{config.kibana.version}-darwin-x86_64.tar.gz',
'tar xzvf filebeat-{config.kibana.version}-darwin-x86_64.tar.gz',
'cd filebeat-{config.kibana.version}-darwin-x86_64/',
]
},
DEB: {
title: 'Download and install Filebeat',
textPre: 'First time using Filebeat? See the [Getting Started Guide]' +
'({config.docs.beats.filebeat}/filebeat-getting-started.html).',
commands: [
'curl -L -O https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-{config.kibana.version}-amd64.deb',
'sudo dpkg -i filebeat-{config.kibana.version}-amd64.deb'
],
textPost: 'Looking for the 32 bits packages? See the [Download page](https://www.elastic.co/downloads/beats/filebeat).'
},
RPM: {
title: 'Download and install Filebeat',
textPre: 'First time using Filebeat? See the [Getting Started Guide]' +
'({config.docs.beats.filebeat}/filebeat-getting-started.html).',
commands: [
'curl -L -O https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-{config.kibana.version}-x86_64.rpm',
'sudo rpm -vi filebeat-{config.kibana.version}-x86_64.rpm'
],
textPost: 'Looking for the 32 bits packages? See the [Download page](https://www.elastic.co/downloads/beats/filebeat).'
},
WINDOWS: {
title: 'Download and install Filebeat',
textPre: 'First time using Filebeat? See the [Getting Started Guide]' +
'({config.docs.beats.filebeat}/filebeat-getting-started.html).\n' +
'1. Download the Filebeat Windows zip file from the [downloads](https://www.elastic.co/downloads/beats/filebeat) page.\n' +
'2. Extract the contents of the zip file into `C:\\Program Files`.\n' +
'3. Rename the `filebeat-{config.kibana.version}-windows` directory to `Filebeat`.\n' +
'4. Open a PowerShell prompt as an Administrator (right-click the PowerShell icon and select' +
' Run As Administrator). If you are running Windows XP, you may need to download and install PowerShell.\n' +
'5. From the PowerShell prompt, run the following commands to install Filebeat as a Windows service.',
commands: [
'PS > cd C:\\Program Files\\Filebeat',
'PS C:\\Program Files\\Filebeat> .\\install-service-filebeat.ps1'
],
textPost: 'Modify the settings under `output.elasticsearch` in the ' +
'`C:\\Program Files\\Filebeat\\filebeat.yml` file to point to your Elasticsearch installation.'
}
},
START: {
OSX: {
title: 'Start Filebeat',
textPre: 'The `setup` command loads the Kibana dashboards.' +
' If the dashboards are already set up, omit this command.',
commands: [
'./filebeat setup',
'./filebeat -e',
]
},
DEB: {
title: 'Start Filebeat',
textPre: 'The `setup` command loads the Kibana dashboards. If the dashboards are already set up, ' +
'omit this command.',
commands: [
'sudo filebeat setup',
'sudo service filebeat start',
]
},
RPM: {
title: 'Start Filebeat',
textPre: 'The `setup` command loads the Kibana dashboards. If the dashboards are already set up, ' +
'omit this command.',
commands: [
'sudo filebeat setup',
'sudo service filebeat start',
],
},
WINDOWS: {
title: 'Start Filebeat',
textPre: 'The `setup` command loads the Kibana dashboards. If the dashboards are already set up, ' +
'omit this command.',
commands: [
'PS C:\\Program Files\\Filebeat> filebeat.exe setup',
'PS C:\\Program Files\\Filebeat> Service-Start filebeat',
]
}
},
CONFIG: {
OSX: {
title: 'Edit the configuration',
textPre: 'Modify `filebeat.yml` to set the connection information:',
commands: [
'output.elasticsearch:',
' hosts: ["<es_url>"]',
' username: "elastic"',
' password: "<password>"',
'setup.kibana:',
' host: "<kibana_url>"'
],
textPost: 'Where `<password>` is the password of the `elastic` user, ' +
'`<es_url>` is the URL of Elasticsearch, and `<kibana_url>` is the URL of Kibana.'
},
DEB: {
title: 'Edit the configuration',
textPre: 'Modify `/etc/filebeat/filebeat.yml` to set the connection information:',
commands: [
'output.elasticsearch:',
' hosts: ["<es_url>"]',
' username: "elastic"',
' password: "<password>"',
'setup.kibana:',
' host: "<kibana_url>"'
],
textPost: 'Where `<password>` is the password of the `elastic` user, ' +
'`<es_url>` is the URL of Elasticsearch, and `<kibana_url>` is the URL of Kibana.'
},
RPM: {
title: 'Edit the configuration',
textPre: 'Modify `/etc/filebeat/filebeat.yml` to set the connection information:',
commands: [
'output.elasticsearch:',
' hosts: ["<es_url>"]',
' username: "elastic"',
' password: "<password>"',
'setup.kibana:',
' host: "<kibana_url>"'
],
textPost: 'Where `<password>` is the password of the `elastic` user, ' +
'`<es_url>` is the URL of Elasticsearch, and `<kibana_url>` is the URL of Kibana.'
},
WINDOWS: {
title: 'Edit the configuration',
textPre: 'Modify `C:\\Program Files\\Filebeat\\filebeat.yml` to set the connection information:',
commands: [
'output.elasticsearch:',
' hosts: ["<es_url>"]',
' username: "elastic"',
' password: "<password>"',
'setup.kibana:',
' host: "<kibana_url>"'
],
textPost: 'Where `<password>` is the password of the `elastic` user, ' +
'`<es_url>` is the URL of Elasticsearch, and `<kibana_url>` is the URL of Kibana.'
}
},
PLUGINS: {
GEOIP_AND_UA: {
title: 'Install Elasticsearch GeoIP and user agent plugins',
textPre: 'This module requires two Elasticsearch plugins that are not ' +
'installed by default.\n\nFrom the Elasticsearch installation folder, run:',
commands: [
'bin/elasticsearch-plugin install ingest-geoip',
'bin/elasticsearch-plugin install ingest-user-agent'
]
},
GEOIP: {
title: 'Install Elasticsearch GeoIP plugin',
textPre: 'This module requires an Elasticsearch plugin that is not ' +
'installed by default.\n\nFrom the Elasticsearch installation folder, run:',
commands: [
'bin/elasticsearch-plugin install ingest-geoip'
]
}
}
};

View file

@ -0,0 +1,2 @@
export const FILEBEAT_ONPREM_CLOUD_INSTRUCTIONS = {
};

View file

@ -0,0 +1,34 @@
export const INSTRUCTION_VARIANT = {
OSX: 'osx',
DEB: 'deb',
RPM: 'rpm',
DOCKER: 'docker',
WINDOWS: 'windows',
NODE: 'node',
DJANGO: 'django',
FLASK: 'flask'
};
const DISPLAY_MAP = {
[INSTRUCTION_VARIANT.OSX]: 'macOS',
[INSTRUCTION_VARIANT.DEB]: 'DEB',
[INSTRUCTION_VARIANT.RPM]: 'RPM',
[INSTRUCTION_VARIANT.DOCKER]: 'Docker',
[INSTRUCTION_VARIANT.WINDOWS]: 'Windows',
[INSTRUCTION_VARIANT.NODE]: 'Node.js',
[INSTRUCTION_VARIANT.DJANGO]: 'Django',
[INSTRUCTION_VARIANT.FLASK]: 'Flask',
};
/**
* Convert instruction variant id into display text.
*
* @params {String} id - instruction variant id as defined from INSTRUCTION_VARIANT
* @return {String} display name
*/
export function getDisplayText(id) {
if (id in DISPLAY_MAP) {
return DISPLAY_MAP[id];
}
return id;
}

View file

@ -0,0 +1,27 @@
export const LOGSTASH_INSTRUCTIONS = {
INSTALL: {
OSX: [
{
title: 'Download and install the Java Runtime Environment',
textPre: 'Follow the installation instructions [here](https://docs.oracle.com/javase/8/docs/technotes/guides/install/mac_jre.html).'
},
{
title: 'Download and install Logstash',
commands: [
'curl -L -O https://artifacts.elastic.co/downloads/logstash/logstash-{config.kibana.version}.tar.gz',
'tar xzvf logstash-{config.kibana.version}.tar.gz'
]
}
],
WINDOWS: [
{
title: 'Download and install the Java runtime environment',
textPre: 'Follow the installation instructions [here](https://docs.oracle.com/javase/8/docs/technotes/guides/install/windows_jre_install.html).'
},
{
title: 'Download and install Logstash',
textPre: 'Download Logstash from [here](https://artifacts.elastic.co/downloads/logstash/logstash-{config.kibana.version}.zip) and unzip it.'
}
],
}
};

View file

@ -0,0 +1,40 @@
export const METRICBEAT_CLOUD_INSTRUCTIONS = {
CONFIG: {
OSX: {
title: 'Edit the configuration',
textPre: 'Modify `metricbeat.yml` to set the connection information for Elastic Cloud:',
commands: [
'cloud.id: "{config.cloud.id}"',
'cloud.auth: "elastic:<password>"'
],
textPost: 'Where `<password>` is the password of the `elastic` user.'
},
DEB: {
title: 'Edit the configuration',
textPre: 'Modify `/etc/metricbeat/metricbeat.yml` to set the connection information for Elastic Cloud:',
commands: [
'cloud.id: "{config.cloud.id}"',
'cloud.auth: "elastic:<password>"'
],
textPost: 'Where `<password>` is the password of the `elastic` user.'
},
RPM: {
title: 'Edit the configuration',
textPre: 'Modify `/etc/metricbeat/metricbeat.yml` to set the connection information for Elastic Cloud:',
commands: [
'cloud.id: "{config.cloud.id}"',
'cloud.auth: "elastic:<password>"'
],
textPost: 'Where `<password>` is the password of the `elastic` user.'
},
WINDOWS: {
title: 'Edit the configuration',
textPre: 'Modify `C:\\Program Files\\Filebeat\\metricbeat.yml` to set the connection information for Elastic Cloud:',
commands: [
'cloud.id: "{config.cloud.id}"',
'cloud.auth: "elastic:<password>"'
],
textPost: 'Where `<password>` is the password of the `elastic` user.'
}
}
};

View file

@ -0,0 +1,147 @@
export const METRICBEAT_INSTRUCTIONS = {
INSTALL: {
OSX: {
title: 'Download and install Metricbeat',
textPre: 'First time using Metricbeat? See the [Getting Started Guide]' +
'({config.docs.beats.metricbeat}/metricbeat-getting-started.html).',
commands: [
'curl -L -O https://artifacts.elastic.co/downloads/beats/metricbeat/metricbeat-{config.kibana.version}-darwin-x86_64.tar.gz',
'tar xzvf metricbeat-{config.kibana.version}-darwin-x86_64.tar.gz',
'cd metricbeat-{config.kibana.version}-darwin-x86_64/',
]
},
DEB: {
title: 'Download and install Metricbeat',
textPre: 'First time using Metricbeat? See the [Getting Started Guide]' +
'({config.docs.beats.metricbeat}/metricbeat-getting-started.html).',
commands: [
'curl -L -O https://artifacts.elastic.co/downloads/beats/metricbeat/metricbeat-{config.kibana.version}-amd64.deb',
'sudo dpkg -i metricbeat-{config.kibana.version}-amd64.deb'
],
textPost: 'Looking for the 32 bits packages? See the [Download page](https://www.elastic.co/downloads/beats/metricbeat).'
},
RPM: {
title: 'Download and install Metricbeat',
textPre: 'First time using Metricbeat? See the [Getting Started Guide]' +
'({config.docs.beats.metricbeat}/metricbeat-getting-started.html).',
commands: [
'curl -L -O https://artifacts.elastic.co/downloads/beats/metricbeat/metricbeat-{config.kibana.version}-x86_64.rpm',
'sudo rpm -vi metricbeat-{config.kibana.version}-x86_64.rpm'
],
textPost: 'Looking for the 32 bits packages? See the [Download page](https://www.elastic.co/downloads/beats/metricbeat).'
},
WINDOWS: {
title: 'Download and install Metricbeat',
textPre: 'First time using Metricbeat? See the [Getting Started Guide]' +
'({config.docs.beats.metricbeat}/metricbeat-getting-started.html).\n' +
'1. Download the Metricbeat Windows zip file from the [downloads](https://www.elastic.co/downloads/beats/metricbeat) page.\n' +
'2. Extract the contents of the zip file into `C:\\Program Files`.\n' +
'3. Rename the `metricbeat-{config.kibana.version}-windows` directory to `Metricbeat`.\n' +
'4. Open a PowerShell prompt as an Administrator (right-click the PowerShell icon and select' +
' Run As Administrator). If you are running Windows XP, you may need to download and install PowerShell.\n' +
'5. From the PowerShell prompt, run the following commands to install Metricbeat as a Windows service.',
commands: [
'PS > cd C:\\Program Files\\Metricbeat',
'PS C:\\Program Files\\Metricbeat> .\\install-service-metricbeat.ps1'
],
textPost: 'Modify the settings under `output.elasticsearch` in the ' +
'`C:\\Program Files\\Metricbeat\\metricbeat.yml` file to point to your Elasticsearch installation.'
}
},
START: {
OSX: {
title: 'Start Metricbeat',
textPre: 'The `setup` command loads the Kibana dashboards.' +
' If the dashboards are already set up, omit this command.',
commands: [
'./metricbeat setup',
'./metricbeat -e',
]
},
DEB: {
title: 'Start Metricbeat',
textPre: 'The `setup` command loads the Kibana dashboards. If the dashboards are already set up, ' +
'omit this command.',
commands: [
'sudo metricbeat setup',
'sudo service metricbeat start',
]
},
RPM: {
title: 'Start Metricbeat',
textPre: 'The `setup` command loads the Kibana dashboards. If the dashboards are already set up, ' +
'omit this command.',
commands: [
'sudo metricbeat setup',
'sudo service metricbeat start',
],
},
WINDOWS: {
title: 'Start Metricbeat',
textPre: 'The `setup` command loads the Kibana dashboards. If the dashboards are already set up, ' +
'omit this command.',
commands: [
'PS C:\\Program Files\\Metricbeat> metricbeat.exe setup',
'PS C:\\Program Files\\Metricbeat> Service-Start metricbeat',
]
}
},
CONFIG: {
OSX: {
title: 'Edit the configuration',
textPre: 'Modify `metricbeat.yml` to set the connection information:',
commands: [
'output.elasticsearch:',
' hosts: ["<es_url>"]',
' username: "elastic"',
' password: "<password>"',
'setup.kibana:',
' host: "<kibana_url>"'
],
textPost: 'Where `<password>` is the password of the `elastic` user, ' +
'`<es_url>` is the URL of Elasticsearch, and `<kibana_url>` is the URL of Kibana.'
},
DEB: {
title: 'Edit the configuration',
textPre: 'Modify `/etc/metricbeat/metricbeat.yml` to set the connection information:',
commands: [
'output.elasticsearch:',
' hosts: ["<es_url>"]',
' username: "elastic"',
' password: "<password>"',
'setup.kibana:',
' host: "<kibana_url>"'
],
textPost: 'Where `<password>` is the password of the `elastic` user, ' +
'`<es_url>` is the URL of Elasticsearch, and `<kibana_url>` is the URL of Kibana.'
},
RPM: {
title: 'Edit the configuration',
textPre: 'Modify `/etc/metricbeat/metricbeat.yml` to set the connection information:',
commands: [
'output.elasticsearch:',
' hosts: ["<es_url>"]',
' username: "elastic"',
' password: "<password>"',
'setup.kibana:',
' host: "<kibana_url>"'
],
textPost: 'Where `<password>` is the password of the `elastic` user, ' +
'`<es_url>` is the URL of Elasticsearch, and `<kibana_url>` is the URL of Kibana.'
},
WINDOWS: {
title: 'Edit the configuration',
textPre: 'Modify `C:\\Program Files\\Metricbeat\\metricbeat.yml` to set the connection information:',
commands: [
'output.elasticsearch:',
' hosts: ["<es_url>"]',
' username: "elastic"',
' password: "<password>"',
'setup.kibana:',
' host: "<kibana_url>"'
],
textPost: 'Where `<password>` is the password of the `elastic` user, ' +
'`<es_url>` is the URL of Elasticsearch, and `<kibana_url>` is the URL of Kibana.'
}
}
};

View file

@ -0,0 +1,16 @@
export const TRYCLOUD_OPTION1 = {
title: 'Option 1: Try module in Elastic Cloud',
textPre: 'Go to [Elastic Cloud](https://cloud.elastic.co/). Register if you ' +
'don\'t have an account.\n' +
' * Select **Create Cluster**, leave size slider at 4 GB RAM, and click **Create**.\n' +
' * Wait for the cluster plan to complete.\n' +
' * Go to the new Cloud Kibana instance and follow the Kibana Home instructions.'
};
export const TRYCLOUD_OPTION2 = {
title: 'Option 2: Connect local Kibana to a Cloud instance',
textPre: 'If you are running this Kibana instance against a hosted Elasticsearch instance,' +
' proceed with manual setup.\n\n' +
'In **Overview >> Endpoints** note **Elasticsearch** as `<es_url>`.'
};

View file

@ -0,0 +1,4 @@
export const PARAM_TYPES = {
NUMBER: 'number',
STRING: 'string'
};

View file

@ -0,0 +1,5 @@
export const TUTORIAL_CATEGORY = {
LOGGING: 'logging',
SECURITY: 'security',
METRICS: 'metrics'
};

View file

@ -0,0 +1,75 @@
import Joi from 'joi';
import { PARAM_TYPES } from './param_types';
import { TUTORIAL_CATEGORY } from './tutorial_category';
const dashboardSchema = Joi.object({
title: Joi.string().required(),
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()
}),
// Kibana dashboards created by this product.
dashboards: Joi.array().items(dashboardSchema).required()
});
const instructionSchema = Joi.object({
title: Joi.string(),
textPre: Joi.string(),
commands: Joi.array().items(Joi.string()),
textPost: Joi.string()
});
const instructionVariantSchema = Joi.object({
id: Joi.string().required(),
instructions: Joi.array().items(instructionSchema).required()
});
const instructionSetSchema = Joi.object({
title: Joi.string(),
// Variants (OSes, languages, etc.) for which tutorial instructions are specified.
instructionVariants: Joi.array().items(instructionVariantSchema).required()
});
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(),
shortDescription: Joi.string().required(),
iconPath: Joi.string(),
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.required(),
// kibana running on prem and elastic cluster running in elastic's cloud
onPremElasticCloud: instructionsSchema.required(),
// Elastic stack artifacts produced by product when it is setup and run.
artifacts: artifactsSchema,
};

View file

@ -8,9 +8,11 @@ import search from './server/routes/api/search';
import { scrollSearchApi } from './server/routes/api/scroll_search';
import { importApi } from './server/routes/api/import';
import { exportApi } from './server/routes/api/export';
import { homeApi } from './server/routes/api/home';
import scripts from './server/routes/api/scripts';
import { registerSuggestionsApi } from './server/routes/api/suggestions';
import { registerFieldFormats } from './server/field_formats/register';
import { registerTutorials } from './server/tutorials/register';
import * as systemApi from './server/lib/system_api';
import handleEsError from './server/lib/handle_es_error';
import mappings from './mappings.json';
@ -147,9 +149,10 @@ export default function (kibana) {
scrollSearchApi(server);
importApi(server);
exportApi(server);
homeApi(server);
registerSuggestionsApi(server);
registerFieldFormats(server);
registerTutorials(server);
server.expose('systemApi', systemApi);
server.expose('handleEsError', handleEsError);
server.expose('injectVars', injectVars);

View file

@ -52,7 +52,7 @@ export class FeatureDirectory extends React.Component {
renderTabs = () => {
return this.tabs.map((tab, index) => (
<KuiTab
className="homeFeatureCategoryTab"
className="homeDirectoryTab"
onClick={() => this.onSelectedTabChanged(tab.id)}
isSelected={tab.id === this.state.selectedTabId}
key={index}
@ -97,10 +97,10 @@ export class FeatureDirectory extends React.Component {
</h1>
</div>
<div className="kuiViewContentItem kuiVerticalRhythmXLarge">
<KuiTabs className="homeFeatureDirectoryTabs">
<KuiTabs className="homeDirectoryTabs">
{this.renderTabs()}
</KuiTabs>
<KuiFlexGrid columns={4} className="homeFeatureDirectory">
<KuiFlexGrid columns={4} className="homeDirectory">
{ this.renderDirectories() }
</KuiFlexGrid>
</div>

View file

@ -3,6 +3,12 @@ import PropTypes from 'prop-types';
import { Synopsis } from './synopsis';
import {
KuiLinkButton,
KuiCardGroup,
KuiCard,
KuiCardDescription,
KuiCardDescriptionTitle,
KuiCardDescriptionText,
KuiCardFooter,
} from 'ui_framework/components';
import {
@ -18,6 +24,9 @@ import {
import { FeatureCatalogueCategory } from 'ui/registry/feature_catalogue';
import chrome from 'ui/chrome';
const kbnBaseUrl = chrome.getInjected('kbnBaseUrl');
export function Home({ addBasePath, directories }) {
const renderDirectories = (category) => {
@ -39,6 +48,95 @@ export function Home({ addBasePath, directories }) {
});
};
const renderPromo = () => {
const cardStyle = {
width: '250px',
'minWidth': '200px'
};
return (
<div className="kuiVerticalRhythm">
<KuiCardGroup>
<KuiCard style={cardStyle}>
<KuiCardDescription>
<KuiCardDescriptionTitle>
<img
src={addBasePath('/plugins/kibana/assets/app_logging.svg')}
/>
<p>
Logging
</p>
</KuiCardDescriptionTitle>
<KuiCardDescriptionText>
Ingest logs from popular data sources and easily visualize in preconfigured dashboards.
</KuiCardDescriptionText>
</KuiCardDescription>
<KuiCardFooter>
<KuiLinkButton
buttonType="secondary"
href={addBasePath(`${kbnBaseUrl}#/home/tutorial_directory/logging`)}
>
Add data
</KuiLinkButton>
</KuiCardFooter>
</KuiCard>
<KuiCard style={cardStyle}>
<KuiCardDescription>
<KuiCardDescriptionTitle>
<img
src={addBasePath('/plugins/kibana/assets/app_monitoring.svg')}
/>
<p>
Metrics
</p>
</KuiCardDescriptionTitle>
<KuiCardDescriptionText>
Collect metrics from the operating system and services running on your servers.
</KuiCardDescriptionText>
</KuiCardDescription>
<KuiCardFooter>
<KuiLinkButton
buttonType="secondary"
href={addBasePath(`${kbnBaseUrl}#/home/tutorial_directory/metrics`)}
>
Add data
</KuiLinkButton>
</KuiCardFooter>
</KuiCard>
<KuiCard style={cardStyle}>
<KuiCardDescription>
<KuiCardDescriptionTitle>
<img
src={addBasePath('/plugins/kibana/assets/app_security.svg')}
/>
<p>
Security Analytics
</p>
</KuiCardDescriptionTitle>
<KuiCardDescriptionText>
Centralize security events for interactive investigation in ready-to-go visualizations.
</KuiCardDescriptionText>
</KuiCardDescription>
<KuiCardFooter>
<KuiLinkButton
buttonType="secondary"
href={addBasePath(`${kbnBaseUrl}#/home/tutorial_directory/security`)}
>
Add data
</KuiLinkButton>
</KuiCardFooter>
</KuiCard>
</KuiCardGroup>
</div>
);
};
return (
<EuiPage className="home">
@ -49,7 +147,7 @@ export function Home({ addBasePath, directories }) {
>
<EuiFlexItem>
<EuiTitle size="l">
<h1>Welcome to Kibana</h1>
<h1>Add Data to Kibana</h1>
</EuiTitle>
</EuiFlexItem>
@ -74,6 +172,13 @@ export function Home({ addBasePath, directories }) {
</EuiFlexItem>
</EuiFlexGroup>
<p className="kuiText kuiSubduedText kuiVerticalRhythm kuiVerticalRhythmSmall">
These turnkey solutions will help you quickly add data into Kibana and turn it into
pre-built dashboards and monitoring systems.
</p>
{ renderPromo() }
<EuiSpacer size="l" />
<EuiFlexGroup className="kuiVerticalRhythm">

View file

@ -2,16 +2,51 @@ import React from 'react';
import PropTypes from 'prop-types';
import { Home } from './home';
import { FeatureDirectory } from './feature_directory';
import { TutorialDirectory } from './tutorial_directory';
import { Tutorial } from './tutorial/tutorial';
import {
HashRouter as Router,
Switch,
Route
} from 'react-router-dom';
import { getTutorial } from '../load_tutorials';
import { replaceTemplateStrings } from './tutorial/replace_template_strings';
import chrome from 'ui/chrome';
export function HomeApp({ addBasePath, directories }) {
const renderTutorialDirectory = (props) => {
return (
<TutorialDirectory
addBasePath={addBasePath}
openTab={props.match.params.tab}
/>
);
};
const renderTutorial = (props) => {
return (
<Tutorial
addBasePath={addBasePath}
isCloudEnabled={chrome.getInjected('isCloudEnabled', false)}
getTutorial={getTutorial}
replaceTemplateStrings={replaceTemplateStrings}
tutorialId={props.match.params.id}
/>
);
};
return (
<Router>
<Switch>
<Route
path="/home/tutorial/:id"
render={renderTutorial}
/>
<Route
path="/home/tutorial_directory/:tab?"
render={renderTutorialDirectory}
/>
<Route
path="/home/feature_directory"
>

View file

@ -0,0 +1,13 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render content with markdown 1`] = `
<div
className="kuiText kuiSubduedText tutorialContent markdown-body"
dangerouslySetInnerHTML={
Object {
"__html": "<p>I am <em>some</em> <a href=\\"https://en.wikipedia.org/wiki/Content\\">content</a> with <code>markdown</code></p>
",
}
}
/>
`;

View file

@ -0,0 +1,133 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render ELASTIC_CLOUD instructions when isCloudEnabled is true 1`] = `
<div
className="kuiView home"
>
<div
className="kuiViewContent kuiViewContent--constrainedWidth"
>
<a
className="kuiLink"
href="#/home"
>
Home
</a>
/
<a
className="kuiLink"
href="#/home/tutorial_directory"
>
Add Data
</a>
<div>
<Introduction
description="tutorial used to drive jest tests"
title="jest test tutorial"
/>
<div
className="text-center kuiVerticalRhythm"
/>
<div
className="homePanel kuiVerticalRhythm"
>
<InstructionSet
instructionVariants={
Array [
Object {
"id": "platform id",
"instructions": Array [
Object {
"title": "elasticCloud instructions",
},
],
},
]
}
key="0"
offset={1}
paramValues={Object {}}
replaceTemplateStrings={[Function]}
setParameter={[Function]}
title="Instruction title"
/>
</div>
</div>
</div>
</div>
`;
exports[`should render ON_PREM instructions with instructions cloud toggle when isCloudEnabled is false 1`] = `
<div
className="kuiView home"
>
<div
className="kuiViewContent kuiViewContent--constrainedWidth"
>
<a
className="kuiLink"
href="#/home"
>
Home
</a>
/
<a
className="kuiLink"
href="#/home/tutorial_directory"
>
Add Data
</a>
<div>
<Introduction
description="tutorial used to drive jest tests"
title="jest test tutorial"
/>
<div
className="text-center kuiVerticalRhythm"
>
<RadioButtonGroup
buttons={
Array [
Object {
"dataTestSubj": "onPremBtn",
"label": "On premise",
"onClick": [Function],
},
Object {
"dataTestSubj": "onPremElasticCloudBtn",
"label": "Elastic Cloud",
"onClick": [Function],
},
]
}
selectedBtnLabel="On premise"
/>
</div>
<div
className="homePanel kuiVerticalRhythm"
>
<InstructionSet
instructionVariants={
Array [
Object {
"id": "platform id",
"instructions": Array [
Object {
"title": "onPrem instructions",
},
],
},
]
}
key="0"
offset={1}
paramValues={Object {}}
replaceTemplateStrings={[Function]}
setParameter={[Function]}
title="Instruction title"
/>
</div>
</div>
</div>
</div>
`;

View file

@ -0,0 +1,23 @@
import classNames from 'classnames';
import React from 'react';
import PropTypes from 'prop-types';
import MarkdownIt from 'markdown-it';
const markdownIt = new MarkdownIt('zero', { html: false, linkify: true });
// list of rules can be found at https://github.com/markdown-it/markdown-it/issues/361
markdownIt.enable(['backticks', 'emphasis', 'link', 'list']);
export function Content({ className, text }) {
const classes = classNames('kuiText kuiSubduedText tutorialContent markdown-body', className);
return (
<div
className={classes}
dangerouslySetInnerHTML={{ __html: markdownIt.render(text) }}
/>
);
}
Content.propTypes = {
className: PropTypes.string,
text: PropTypes.string.isRequired
};

View file

@ -0,0 +1,13 @@
import React from 'react';
import { shallow } from 'enzyme';
import {
Content,
} from './content';
test('should render content with markdown', () => {
const component = shallow(<Content
text={'I am *some* [content](https://en.wikipedia.org/wiki/Content) with `markdown`'}
/>);
expect(component).toMatchSnapshot(); // eslint-disable-line
});

View file

@ -0,0 +1,60 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Tooltip } from 'pivotal-ui/react/tooltip';
import { OverlayTrigger } from 'pivotal-ui/react/overlay-trigger';
import { KuiButton } from 'ui_framework/components';
import { copyToClipboard } from '../../copy_to_clipboard';
const UNCOPIED_MSG = 'Copy to clipboard';
const COPIED_MSG = 'Copied';
export class CopyButton extends React.Component {
constructor(props) {
super(props);
this.state = {
tooltipText: UNCOPIED_MSG
};
}
copySnippet = () => {
const isCopied = copyToClipboard(this.props.textToCopy);
if (isCopied) {
this.setState({
tooltipText: COPIED_MSG,
});
}
}
resetTooltipText = () => {
this.setState({
tooltipText: UNCOPIED_MSG,
});
}
render() {
return (
<OverlayTrigger
placement="top"
overlay={
<Tooltip>
{this.state.tooltipText}
</Tooltip>
}
>
<KuiButton
buttonType="secondary"
onClick={this.copySnippet}
onMouseOut={this.resetTooltipText}
>
Copy snippet
</KuiButton>
</OverlayTrigger>
);
}
}
CopyButton.propTypes = {
textToCopy: PropTypes.string.isRequired,
};

View file

@ -0,0 +1,85 @@
import './instruction.less';
import React from 'react';
import PropTypes from 'prop-types';
import { Content } from './content';
import { CopyButton } from './copy_button';
import {
EuiCodeBlock,
EuiFlexGroup,
EuiFlexItem,
EuiSpacer,
} from '@elastic/eui';
export function Instruction({ commands, paramValues, textPost, textPre, replaceTemplateStrings }) {
let pre;
if (textPre) {
pre = (
<Content
text={replaceTemplateStrings(textPre)}
/>
);
}
let post;
if (textPost) {
post = (
<div>
<EuiSpacer size="s" />
<Content
text={replaceTemplateStrings(textPost)}
/>
</div>
);
}
let copyButton;
let commandBlock;
if (commands) {
const cmdText = commands.map(cmd => { return replaceTemplateStrings(cmd, paramValues); }).join('\n');
copyButton = (
<CopyButton
textToCopy={cmdText}
/>
);
commandBlock = (
<div>
<EuiSpacer size="s" />
<EuiCodeBlock language="sh">
{cmdText}
</EuiCodeBlock>
</div>
);
}
return (
<div className="instruction">
<EuiFlexGroup justifyContent="spaceBetween" alignItems="flexEnd">
<EuiFlexItem grow={false}>
{pre}
</EuiFlexItem>
<EuiFlexItem
style={{ minWidth: 114 }}
grow={false}
>
{copyButton}
</EuiFlexItem>
</EuiFlexGroup>
{commandBlock}
{post}
</div>
);
}
Instruction.propTypes = {
commands: PropTypes.array,
paramValues: PropTypes.object.isRequired,
textPost: PropTypes.string,
textPre: PropTypes.string,
replaceTemplateStrings: PropTypes.func.isRequired,
};

View file

@ -0,0 +1,8 @@
@import (reference) "~ui/styles/variables.less";
.instruction {
border-left: medium solid @globalColorLightGray;
margin-left: 16px;
padding-left: 24px;
}

View file

@ -0,0 +1,174 @@
import classNames from 'classnames';
import React from 'react';
import PropTypes from 'prop-types';
import {
KuiBar,
KuiBarSection,
KuiTabs,
KuiTab
} from 'ui_framework/components';
import { Instruction } from './instruction';
import { Step } from './step';
import { ParameterForm } from './parameter_form';
import { getDisplayText } from '../../../../common/tutorials/instruction_variant';
export class InstructionSet extends React.Component {
constructor(props) {
super(props);
this.tabs = props.instructionVariants.map((variant) => {
return {
id: variant.id,
name: getDisplayText(variant.id)
};
});
this.state = {
isParamFormVisible: false
};
if (this.tabs.length > 0) {
this.state.selectedTabId = this.tabs[0].id;
}
}
handleToggleVisibility = () => {
this.setState(prevState => (
{ isParamFormVisible: !prevState.isParamFormVisible }
));
}
onSelectedTabChanged = id => {
this.setState({
selectedTabId: id,
});
};
renderTabs = () => {
return this.tabs.map((tab, index) => (
<KuiTab
onClick={() => this.onSelectedTabChanged(tab.id)}
isSelected={tab.id === this.state.selectedTabId}
key={index}
>
{tab.name}
</KuiTab>
));
}
renderInstructions = () => {
const instructionVariant = this.props.instructionVariants.find(variant => {
return variant.id === this.state.selectedTabId;
});
if (!instructionVariant) {
return;
}
return instructionVariant.instructions.map((instruction, index) => (
<Step
className="kuiVerticalRhythm"
key={index}
step={this.props.offset + index}
title={instruction.title}
>
<Instruction
commands={instruction.commands}
paramValues={this.props.paramValues}
textPre={instruction.textPre}
textPost={instruction.textPost}
replaceTemplateStrings={this.props.replaceTemplateStrings}
/>
</Step>
));
}
renderHeader = () => {
let paramsVisibilityToggle;
if (this.props.params) {
const visibilityToggleClasses = classNames('kuiIcon kuiSideBarCollapsibleTitle__caret', {
'fa-caret-right': !this.state.isParamFormVisible,
'fa-caret-down': this.state.isParamFormVisible
});
paramsVisibilityToggle = (
<div className="kuiSideBarCollapsibleTitle" style={{ cursor: 'pointer' }}>
<div
aria-label="toggle command parameters visibility"
className="kuiSideBarCollapsibleTitle__label"
onClick={this.handleToggleVisibility}
>
<span className={visibilityToggleClasses} />
<span className="kuiSideBarCollapsibleTitle__text">
Customize your code snippets
</span>
</div>
</div>
);
}
return (
<KuiBar className="kuiVerticalRhythm">
<KuiBarSection>
<div className="kuiTitle">
{this.props.title}
</div>
</KuiBarSection>
<KuiBarSection>
{paramsVisibilityToggle}
</KuiBarSection>
</KuiBar>
);
}
render() {
let paramsForm;
if (this.props.params && this.state.isParamFormVisible) {
paramsForm = (
<ParameterForm
params={this.props.params}
paramValues={this.props.paramValues}
setParameter={this.props.setParameter}
/>
);
}
return (
<div className="kuiVerticalRhythmLarge">
{this.renderHeader()}
{paramsForm}
<KuiTabs className="kuiVerticalRhythm">
{this.renderTabs()}
</KuiTabs>
{this.renderInstructions()}
</div>
);
}
}
const instructionShape = PropTypes.shape({
title: PropTypes.string,
textPre: PropTypes.string,
commands: PropTypes.arrayOf(PropTypes.string),
textPost: PropTypes.string
});
const instructionVariantShape = PropTypes.shape({
id: PropTypes.string.isRequired,
instructions: PropTypes.arrayOf(instructionShape).isRequired,
});
InstructionSet.propTypes = {
title: PropTypes.string.isRequired,
instructionVariants: PropTypes.arrayOf(instructionVariantShape).isRequired,
offset: PropTypes.number.isRequired,
params: PropTypes.array,
paramValues: PropTypes.object.isRequired,
setParameter: PropTypes.func,
replaceTemplateStrings: PropTypes.func.isRequired,
};

View file

@ -0,0 +1,48 @@
import './introduction.less';
import React from 'react';
import PropTypes from 'prop-types';
import { Content } from './content';
import {
EuiImage,
} from '@elastic/eui';
export function Introduction({ description, previewUrl, title }) {
let img;
if (previewUrl) {
img = (
<EuiImage
size="l"
hasShadow
allowFullScreen
fullScreenIconColor="dark"
alt="screenshot of primary dashboard."
url={previewUrl}
/>
);
}
return (
<div className="introduction kuiVerticalRhythm">
<div className="kuiFlexGroup kuiFlexGroup--gutterLarge">
<div className="kuiFlexItem">
<h1 className="kuiTitle kuiVerticalRhythm">
{title}
</h1>
<Content className="kuiVerticalRhythm" text={description}/>
</div>
<div className="kuiFlexItem kuiFlexItem--flexGrowZero">
{img}
</div>
</div>
</div>
);
}
Introduction.propTypes = {
description: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
previewUrl: PropTypes.string
};

View file

@ -0,0 +1,3 @@
.introduction {
margin: 24px;
}

View file

@ -0,0 +1,33 @@
import React from 'react';
import PropTypes from 'prop-types';
export function NumberParameter({ id, label, value, setParameter }) {
const handleChange = (evt) => {
setParameter(id, parseFloat(evt.target.value));
};
return (
<div className="kuiSideBarFormRow">
<label
className="kuiSideBarFormRow__label"
>
{label}
</label>
<div className="kuiSideBarFormRow__control kuiFieldGroupSection--wide">
<input
className="kuiTextInput"
type="number"
value={value}
onChange={handleChange}
/>
</div>
</div>
);
}
NumberParameter.propTypes = {
id: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
value: PropTypes.number.isRequired,
setParameter: PropTypes.func.isRequired,
};

View file

@ -0,0 +1,60 @@
import React from 'react';
import PropTypes from 'prop-types';
import { NumberParameter } from './number_parameter';
import { StringParameter } from './string_parameter';
export class ParameterForm extends React.Component {
renderInputs = () => {
return this.props.params.map(param => {
switch (param.type) {
case 'number':
return (
<NumberParameter
key={param.id}
id={param.id}
label={param.label}
value={this.props.paramValues[param.id]}
setParameter={this.props.setParameter}
/>
);
case 'string':
return (
<StringParameter
key={param.id}
id={param.id}
label={param.label}
value={this.props.paramValues[param.id]}
setParameter={this.props.setParameter}
/>
);
default:
throw new Error(`Unhandled parameter type ${param.type}`);
}
});
}
render() {
return (
<div>
<div className="kuiSideBarSection">
{this.renderInputs()}
</div>
</div>
);
}
}
const paramsShape = PropTypes.shape({
id: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
type: PropTypes.string.isRequired,
});
ParameterForm.propTypes = {
params: PropTypes.arrayOf(paramsShape).isRequired,
paramValues: PropTypes.object.isRequired,
setParameter: PropTypes.func.isRequired
};

View file

@ -0,0 +1,74 @@
import './radio_button_group.less';
import React from 'react';
import PropTypes from 'prop-types';
import {
KuiButtonGroup,
KuiButton
} from 'ui_framework/components';
export class RadioButtonGroup extends React.Component {
constructor(props) {
super(props);
this.state = {};
if (props.buttons.length > 0) {
const matchingButton = props.buttons.find(button => {
return props.selectedBtnLabel === button.label;
});
if (matchingButton) {
this.state.selectedBtnLabel = props.selectedBtnLabel;
} else {
this.state.selectedBtnLabel = props.buttons[0].label;
}
}
}
renderButtons = () => {
return this.props.buttons.map((button, index) => {
const handleOnClick = () => {
this.setState({
selectedBtnLabel: button.label
});
button.onClick();
};
let buttonType = 'secondary';
if (button.label === this.state.selectedBtnLabel) {
buttonType = 'primary';
}
return (
<KuiButton
className="kuiRadioButton"
buttonType={buttonType}
onClick={handleOnClick}
key={index}
data-test-subj={button.dataTestSubj}
>
{button.label}
</KuiButton>
);
});
}
render = () => {
return (
<KuiButtonGroup
className="radioButtonGroup"
isUnited
>
{this.renderButtons()}
</KuiButtonGroup>
);
}
}
RadioButtonGroup.propTypes = {
buttons: PropTypes.arrayOf(PropTypes.shape({
onClick: PropTypes.func.isRequired,
label: PropTypes.string.isRequired,
dataTestSubj: PropTypes.string
})).isRequired,
selectedBtnLabel: PropTypes.string
};

View file

@ -0,0 +1,10 @@
// remove space between buttons
.kuiRadioButton {
margin-left: 0px !important;
}
// give primary button same border as secondary button so they are even heights when placed side-by-side
.kuiRadioButton.kuiButton--primary {
border: solid 1px #0079a5;
}

View file

@ -0,0 +1,35 @@
import Mustache from 'mustache';
import chrome from 'ui/chrome';
import { metadata } from 'ui/metadata';
import {
DOC_LINK_VERSION,
ELASTIC_WEBSITE_URL,
documentationLinks
} from 'ui/documentation_links/documentation_links';
const TEMPLATE_TAGS = ['{', '}'];
export function replaceTemplateStrings(text, params = {}) {
const variables = {
config: {
cloud: {
id: chrome.getInjected('cloudId')
},
docs: {
base_url: ELASTIC_WEBSITE_URL,
beats: {
filebeat: documentationLinks.filebeat.base,
metricbeat: documentationLinks.metricbeat.base
},
logstash: documentationLinks.logstash.base,
version: DOC_LINK_VERSION
},
kibana: {
version: metadata.version
}
},
params: params
};
Mustache.parse(text, TEMPLATE_TAGS);
return Mustache.render(text, variables);
}

View file

@ -0,0 +1,30 @@
import './step.less';
import React from 'react';
import PropTypes from 'prop-types';
export function Step({ children, step, title }) {
return (
<div className="kuiVerticalRhythm">
<div className="kuiVerticalRhythm">
<div className="kuiSubTitle step">
{step}
</div>
<h3 className="kuiSubTitle title">
{title}
</h3>
</div>
<div className="kuiVerticalRhythm">
{children}
</div>
</div>
);
}
Step.propTypes = {
children: PropTypes.node.isRequired,
step: PropTypes.number.isRequired,
title: PropTypes.string.isRequired,
};

View file

@ -0,0 +1,17 @@
@import (reference) "~ui/styles/variables.less";
.step {
width: 32px;
height: 32px;
display: inline-block;
line-height: 32px;
text-align: center;
color: @white;
border-radius: 100%;
background-color: @globalColorBlue;
}
.title {
display: inline-block;
margin-left: 16px;
}

View file

@ -0,0 +1,33 @@
import React from 'react';
import PropTypes from 'prop-types';
export function StringParameter({ id, label, value, setParameter }) {
const handleChange = (evt) => {
setParameter(id, evt.target.value);
};
return (
<div className="kuiSideBarFormRow">
<label
className="kuiSideBarFormRow__label"
>
{label}
</label>
<div className="kuiSideBarFormRow__control kuiFieldGroupSection--wide">
<input
className="kuiTextInput"
type="text"
value={value}
onChange={handleChange}
/>
</div>
</div>
);
}
StringParameter.propTypes = {
id: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
value: PropTypes.string.isRequired,
setParameter: PropTypes.func.isRequired,
};

View file

@ -0,0 +1,202 @@
import './tutorial.less';
import _ from 'lodash';
import React from 'react';
import PropTypes from 'prop-types';
import { Introduction } from './introduction';
import { InstructionSet } from './instruction_set';
import { RadioButtonGroup } from './radio_button_group';
const INSTRUCTIONS_TYPE = {
ELASTIC_CLOUD: 'elasticCloud',
ON_PREM: 'onPrem',
ON_PREM_ELASTIC_CLOUD: 'onPremElasticCloud'
};
export class Tutorial extends React.Component {
constructor(props) {
super(props);
this.state = {
notFound: false,
paramValues: {},
tutorial: null
};
if (props.isCloudEnabled) {
this.state.visibleInstructions = INSTRUCTIONS_TYPE.ELASTIC_CLOUD;
} else {
this.state.visibleInstructions = INSTRUCTIONS_TYPE.ON_PREM;
}
}
componentWillMount() {
this._isMounted = true;
}
componentWillUnmount() {
this._isMounted = false;
}
async componentDidMount() {
const tutorial = await this.props.getTutorial(this.props.tutorialId);
if (!this._isMounted) {
return;
}
if (tutorial) {
// eslint-disable-next-line react/no-did-mount-set-state
this.setState({
tutorial: tutorial
}, this.setParamDefaults);
} else {
// eslint-disable-next-line react/no-did-mount-set-state
this.setState({
notFound: true,
});
}
}
getInstructions = () => {
if (!this.state.tutorial) {
return { instructionSets: [] };
}
switch(this.state.visibleInstructions) {
case INSTRUCTIONS_TYPE.ELASTIC_CLOUD:
return this.state.tutorial.elasticCloud;
case INSTRUCTIONS_TYPE.ON_PREM:
return this.state.tutorial.onPrem;
case INSTRUCTIONS_TYPE.ON_PREM_ELASTIC_CLOUD:
return this.state.tutorial.onPremElasticCloud;
default:
throw new Error(`Unhandled instruction type ${this.state.visibleInstructions}`);
}
}
setParamDefaults = () => {
const instructions = this.getInstructions();
const paramValues = {};
if (instructions.params) {
instructions.params.forEach((param => {
paramValues[param.id] = param.defaultValue;
}));
}
this.setState({
paramValues: paramValues
});
}
setVisibleInstructions = (instructionsType) => {
this.setState({
visibleInstructions: instructionsType
}, this.setParamDefaults);
}
setParameter = (paramId, newValue) => {
this.setState(previousState => {
const paramValues = _.cloneDeep(previousState.paramValues);
paramValues[paramId] = newValue;
return { paramValues: paramValues };
});
}
onPrem = () => {
this.setVisibleInstructions(INSTRUCTIONS_TYPE.ON_PREM);
}
onPremElasticCloud = () => {
this.setVisibleInstructions(INSTRUCTIONS_TYPE.ON_PREM_ELASTIC_CLOUD);
}
renderInstructionSetsToggle = () => {
if (!this.props.isCloudEnabled) {
const radioButtons = [
{ onClick: this.onPrem, label: 'On premise', dataTestSubj: 'onPremBtn' },
{ onClick: this.onPremElasticCloud, label: 'Elastic Cloud', dataTestSubj: 'onPremElasticCloudBtn' },
];
return (
<RadioButtonGroup
buttons={radioButtons}
selectedBtnLabel={radioButtons[0].label}
/>
);
}
}
renderInstructionSets = (instructions) => {
let offset = 1;
return instructions.instructionSets.map((instructionSet, index) => {
const currentOffset = offset;
offset += instructionSet.instructionVariants[0].instructions.length;
return (
<InstructionSet
title={instructionSet.title}
instructionVariants={instructionSet.instructionVariants}
offset={currentOffset}
params={instructions.params}
paramValues={this.state.paramValues}
setParameter={this.setParameter}
replaceTemplateStrings={this.props.replaceTemplateStrings}
key={index}
/>
);
});
}
render() {
let content;
if (this.state.notFound) {
content = (
<div className="homePanel">
<p className="kuiText kuiSubduedText kuiVerticalRhythm kuiVerticalRhythmSmall">
Unable to find tutorial {this.props.tutorialId}
</p>
</div>
);
}
if (this.state.tutorial) {
let previewUrl;
if (this.state.tutorial.previewImagePath) {
previewUrl = this.props.addBasePath(this.state.tutorial.previewImagePath);
}
const instructions = this.getInstructions();
content = (
<div>
<Introduction
title={this.state.tutorial.name}
description={this.props.replaceTemplateStrings(this.state.tutorial.longDescription)}
previewUrl={previewUrl}
/>
<div className="text-center kuiVerticalRhythm">
{this.renderInstructionSetsToggle()}
</div>
<div className="homePanel kuiVerticalRhythm">
{this.renderInstructionSets(instructions)}
</div>
</div>
);
}
return (
<div className="kuiView home">
<div className="kuiViewContent kuiViewContent--constrainedWidth">
<a className="kuiLink" href="#/home">Home</a> / <a className="kuiLink" href="#/home/tutorial_directory">Add Data</a>
{content}
</div>
</div>
);
}
}
Tutorial.propTypes = {
addBasePath: PropTypes.func.isRequired,
isCloudEnabled: PropTypes.bool.isRequired,
getTutorial: PropTypes.func.isRequired,
replaceTemplateStrings: PropTypes.func.isRequired,
tutorialId: PropTypes.string.isRequired
};

View file

@ -0,0 +1,17 @@
.tutorialContent {
/*
* 1. remove bottom margin placed on p element by bootstrap
*/
p {
margin-bottom: 0; /* 1 */
}
}
.text-center > .kuiButtonGroup {
display: inline-block !important;
}
.homePanel {
background: white;
padding: 24px;
}

View file

@ -0,0 +1,87 @@
import React from 'react';
import { shallow, mount } from 'enzyme';
import { findTestSubject } from '@elastic/eui/lib/test';
import {
Tutorial,
} from './tutorial';
function buildInstructionSet(type) {
return {
instructionSets: [
{
title: 'Instruction title',
instructionVariants: [
{
id: 'platform id',
instructions: [
{
title: `${type} instructions`,
}
]
}
]
}
]
};
}
const tutorial = {
name: 'jest test tutorial',
longDescription: 'tutorial used to drive jest tests',
elasticCloud: buildInstructionSet('elasticCloud'),
onPrem: buildInstructionSet('onPrem'),
onPremElasticCloud: buildInstructionSet('onPremElasticCloud')
};
const loadTutorialPromise = Promise.resolve(tutorial);
const getTutorial = () => {
return loadTutorialPromise;
};
const addBasePath = (path) => {
return `BASE_PATH/${path}`;
};
const replaceTemplateStrings = (text) => {
return text;
};
test('should render ON_PREM instructions with instructions cloud toggle when isCloudEnabled is false', () => {
const component = shallow(<Tutorial
addBasePath={addBasePath}
isCloudEnabled={false}
getTutorial={getTutorial}
replaceTemplateStrings={replaceTemplateStrings}
tutorialId={'my_testing_tutorial'}
/>);
loadTutorialPromise.then(() => {
component.update();
expect(component).toMatchSnapshot(); // eslint-disable-line
});
});
test('should render ELASTIC_CLOUD instructions when isCloudEnabled is true', () => {
const component = shallow(<Tutorial
addBasePath={addBasePath}
isCloudEnabled={true}
getTutorial={getTutorial}
replaceTemplateStrings={replaceTemplateStrings}
tutorialId={'my_testing_tutorial'}
/>);
loadTutorialPromise.then(() => {
component.update();
expect(component).toMatchSnapshot(); // eslint-disable-line
});
});
test('should display ON_PREM_ELASTIC_CLOUD instructions when cloud toggle is clicked', () => {
const component = mount(<Tutorial
addBasePath={addBasePath}
isCloudEnabled={false}
getTutorial={getTutorial}
replaceTemplateStrings={replaceTemplateStrings}
tutorialId={'my_testing_tutorial'}
/>);
loadTutorialPromise.then(() => {
component.update();
findTestSubject(component, 'onPremElasticCloudBtn').simulate('click');
expect(component.state('visibleInstructions')).toBe('onPremElasticCloud');
});
});

View file

@ -0,0 +1,120 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Synopsis } from './synopsis';
import {
KuiTabs,
KuiTab,
KuiFlexItem,
KuiFlexGrid,
} from 'ui_framework/components';
import { getTutorials } from '../load_tutorials';
const ALL = 'all';
export class TutorialDirectory extends React.Component {
constructor(props) {
super(props);
this.tabs = [{
id: ALL,
name: 'All',
}, {
id: 'logging',
name: 'Logging',
}, {
id: 'metrics',
name: 'Metrics',
}, {
id: 'security',
name: 'Security Analytics',
}];
let openTab = ALL;
if (props.openTab && this.tabs.some(tab => { return tab.id === props.openTab; })) {
openTab = props.openTab;
}
this.state = {
selectedTabId: openTab,
tutorials: []
};
}
async componentWillMount() {
const tutorials = await getTutorials();
this.setState({
tutorials: tutorials,
});
}
onSelectedTabChanged = id => {
this.setState({
selectedTabId: id,
});
};
renderTabs = () => {
return this.tabs.map((tab, index) => (
<KuiTab
className="homeDirectoryTab"
onClick={() => this.onSelectedTabChanged(tab.id)}
isSelected={tab.id === this.state.selectedTabId}
key={index}
>
{tab.name}
</KuiTab>
));
}
renderTutorials = () => {
return this.state.tutorials
.filter((tutorial) => {
if (this.state.selectedTabId === ALL) {
return true;
}
return this.state.selectedTabId === tutorial.category;
})
.map((tutorial) => {
return (
<KuiFlexItem key={tutorial.name}>
<Synopsis
description={tutorial.shortDescription}
title={tutorial.name}
url={this.props.addBasePath(`#/home/tutorial/${tutorial.id}`)}
/>
</KuiFlexItem>
);
});
};
render() {
return (
<div className="kuiView home">
<div className="kuiViewContent">
<div className="kuiViewContentItem kuiVerticalRhythmXLarge">
<a className="kuiLink" href="#/home">Home</a>
<h1 className="kuiTitle ">
Add Data to Kibana
</h1>
</div>
<div className="kuiViewContentItem kuiVerticalRhythmXLarge">
<KuiTabs>
{this.renderTabs()}
</KuiTabs>
<KuiFlexGrid columns={4} className="homeDirectory">
{ this.renderTutorials() }
</KuiFlexGrid>
</div>
</div>
</div>
);
}
}
TutorialDirectory.propTypes = {
addBasePath: PropTypes.func.isRequired,
openTab: PropTypes.string
};

View file

@ -0,0 +1,47 @@
function createHiddenTextElement(text) {
const textElement = document.createElement('span');
textElement.textContent = text;
textElement.style.all = 'unset';
// prevents scrolling to the end of the page
textElement.style.position = 'fixed';
textElement.style.top = 0;
textElement.style.clip = 'rect(0, 0, 0, 0)';
// used to preserve spaces and line breaks
textElement.style.whiteSpace = 'pre';
// do not inherit user-select (it may be `none`)
textElement.style.webkitUserSelect = 'text';
textElement.style.MozUserSelect = 'text';
textElement.style.msUserSelect = 'text';
textElement.style.userSelect = 'text';
return textElement;
}
export function copyToClipboard(text) {
let isCopied = true;
const range = document.createRange();
const selection = document.getSelection();
const elementToBeCopied = createHiddenTextElement(text);
document.body.appendChild(elementToBeCopied);
range.selectNode(elementToBeCopied);
selection.empty();
selection.addRange(range);
if (!document.execCommand('copy')) {
isCopied = false;
console.warn('Unable to copy to clipboard.'); // eslint-disable-line no-console
}
if (selection) {
if (typeof selection.removeRange === 'function') {
selection.removeRange(range);
} else {
selection.removeAllRanges();
}
}
document.body.removeChild(elementToBeCopied);
return isCopied;
}

View file

@ -5,7 +5,19 @@
min-height: 100vh;
}
.homeFeatureDirectory {
.kuiCard__descriptionTitle img {
display: inline-block;
width: 64px;
height: 64px;
margin-bottom: 10px;
}
.kuiCardGroup .kuiCard {
flex: 1 1 0 !important;
background-color: white;
}
.homeDirectory {
background: @white;
margin: 0;
border-left: 1px solid @globalColorLightGray;
@ -14,6 +26,6 @@
padding: 16px;
}
.homeFeatureCategoryTab {
.homeDirectoryTab {
background-color: @globalColorLightestGray;
}

View file

@ -27,3 +27,5 @@ function getRoute() {
// redirect us to the default page by encountering a url it isn't marked as being able to handle.
routes.when('/home', getRoute());
routes.when('/home/feature_directory', getRoute());
routes.when('/home/tutorial_directory/:tab?', getRoute());
routes.when('/home/tutorial/:id', getRoute());

View file

@ -0,0 +1,52 @@
import _ from 'lodash';
import chrome from 'ui/chrome';
import { notify } from 'ui/notify';
const baseUrl = chrome.addBasePath('/api/kibana/home/tutorials');
const headers = new Headers();
headers.append('Accept', 'application/json');
headers.append('Content-Type', 'application/json');
headers.append('kbn-xsrf', 'kibana');
let tutorials = [];
let turorialsLoaded = false;
async function loadTutorials() {
try {
const response = await fetch(baseUrl, {
method: 'get',
credentials: 'include',
headers: headers,
});
if (response.status >= 300) {
throw new Error(`Request failed with status code: ${response.status}`);
}
tutorials = await response.json();
turorialsLoaded = true;
} catch(err) {
notify.error(`Unable to load tutorials, ${err}`);
}
}
export async function getTutorials() {
if (!turorialsLoaded) {
await loadTutorials();
}
return _.cloneDeep(tutorials);
}
export async function getTutorial(id) {
if (!turorialsLoaded) {
await loadTutorials();
}
const tutorial = tutorials.find(tutorial => {
return tutorial.id === id;
});
if (tutorial) {
return _.cloneDeep(tutorial);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 843 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 448 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 328 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 343 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 382 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 550 KiB

View file

@ -0,0 +1,5 @@
import { registerTutorials } from './register_tutorials';
export function homeApi(server) {
registerTutorials(server);
}

View file

@ -0,0 +1,10 @@
export function registerTutorials(server) {
server.route({
path: '/api/kibana/home/tutorials',
method: ['GET'],
handler: async function (req, reply) {
reply(server.getTutorials());
}
});
}

View file

@ -0,0 +1,50 @@
import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant';
import { FILEBEAT_INSTRUCTIONS } from '../../../common/tutorials/filebeat_instructions';
import { FILEBEAT_CLOUD_INSTRUCTIONS } from '../../../common/tutorials/filebeat_cloud_instructions';
import { ENABLE_INSTRUCTIONS } from './enable';
export const ELASTIC_CLOUD_INSTRUCTIONS = {
instructionSets: [
{
title: 'Getting Started',
instructionVariants: [
{
id: INSTRUCTION_VARIANT.OSX,
instructions: [
FILEBEAT_INSTRUCTIONS.INSTALL.OSX,
FILEBEAT_CLOUD_INSTRUCTIONS.CONFIG.OSX,
ENABLE_INSTRUCTIONS.OSX,
FILEBEAT_INSTRUCTIONS.START.OSX
]
},
{
id: INSTRUCTION_VARIANT.DEB,
instructions: [
FILEBEAT_INSTRUCTIONS.INSTALL.DEB,
FILEBEAT_CLOUD_INSTRUCTIONS.CONFIG.DEB,
ENABLE_INSTRUCTIONS.DEB,
FILEBEAT_INSTRUCTIONS.START.DEB
]
},
{
id: INSTRUCTION_VARIANT.RPM,
instructions: [
FILEBEAT_INSTRUCTIONS.INSTALL.RPM,
FILEBEAT_CLOUD_INSTRUCTIONS.CONFIG.RPM,
ENABLE_INSTRUCTIONS.RPM,
FILEBEAT_INSTRUCTIONS.START.RPM
]
},
{
id: INSTRUCTION_VARIANT.WINDOWS,
instructions: [
FILEBEAT_INSTRUCTIONS.INSTALL.WINDOWS,
FILEBEAT_CLOUD_INSTRUCTIONS.CONFIG.WINDOWS,
ENABLE_INSTRUCTIONS.WINDOWS,
FILEBEAT_INSTRUCTIONS.START.WINDOWS
]
}
]
}
]
};

View file

@ -0,0 +1,32 @@
export const ENABLE_INSTRUCTIONS = {
OSX: {
title: 'Enable and configure the apache2 module',
textPre: 'From the installation directory, run:',
commands: [
'./filebeat modules enable apache2',
],
textPost: 'Modify the settings in the `modules.d/apache2.yml` file.'
},
DEB: {
title: 'Enable and configure the apache2 module',
commands: [
'sudo filebeat modules enable apache2',
],
textPost: 'Modify the settings in the `/etc/filebeat/modules.d/apache2.yml` file.'
},
RPM: {
title: 'Enable and configure the apache2 module',
commands: [
'sudo filebeat modules enable apache2',
],
textPost: 'Modify the settings in the `/etc/filebeat/modules.d/apache2.yml` file.'
},
WINDOWS: {
title: 'Enable and configure the apache2 module',
textPre: 'From the `C:\\Program Files\\Filebeat` folder, run:',
commands: [
'PS C:\\Program Files\\Filebeat> filebeat.exe modules enable apache2',
],
textPost: 'Modify the settings in the `modules.d/apache2.yml` file.'
}
};

View file

@ -0,0 +1,34 @@
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { ON_PREM_INSTRUCTIONS } from './on_prem';
import { ELASTIC_CLOUD_INSTRUCTIONS } from './elastic_cloud';
import { ON_PREM_ELASTIC_CLOUD_INSTRUCTIONS } from './on_prem_elastic_cloud';
export function apacheLogsSpecProvider() {
return {
id: 'apacheLogs',
name: 'Apache logs',
category: TUTORIAL_CATEGORY.LOGGING,
shortDescription: 'Collect and parse access and error logs created by the Apache HTTP server.',
longDescription: 'The apache2 Filebeat module parses access and error logs created by the Apache 2 HTTP server.' +
' [Learn more]({config.docs.beats.filebeat}/filebeat-module-apache2.html)' +
' about the apache2 module.',
//iconPath: '', TODO
artifacts: {
dashboards: [
{
title: 'Filebeat-Apache2-Dashboard',
linkLabel: 'Apache2 logs dashboard',
isOverview: true
}
],
exportedFields: {
documentationUrl: '{config.docs.beats.filebeat}/exported-fields-apache2.html'
}
},
completionTimeMinutes: 10,
previewImagePath: '/plugins/kibana/home/tutorial_resources/apache_logs/screenshot.png',
onPrem: ON_PREM_INSTRUCTIONS,
elasticCloud: ELASTIC_CLOUD_INSTRUCTIONS,
onPremElasticCloud: ON_PREM_ELASTIC_CLOUD_INSTRUCTIONS
};
}

View file

@ -0,0 +1,53 @@
import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant';
import { FILEBEAT_INSTRUCTIONS } from '../../../common/tutorials/filebeat_instructions';
import { ENABLE_INSTRUCTIONS } from './enable';
export const ON_PREM_INSTRUCTIONS = {
instructionSets: [
{
title: 'Getting Started',
instructionVariants: [
{
id: INSTRUCTION_VARIANT.OSX,
instructions: [
FILEBEAT_INSTRUCTIONS.PLUGINS.GEOIP_AND_UA,
FILEBEAT_INSTRUCTIONS.INSTALL.OSX,
FILEBEAT_INSTRUCTIONS.CONFIG.OSX,
ENABLE_INSTRUCTIONS.OSX,
FILEBEAT_INSTRUCTIONS.START.OSX
]
},
{
id: INSTRUCTION_VARIANT.DEB,
instructions: [
FILEBEAT_INSTRUCTIONS.PLUGINS.GEOIP_AND_UA,
FILEBEAT_INSTRUCTIONS.INSTALL.DEB,
FILEBEAT_INSTRUCTIONS.CONFIG.DEB,
ENABLE_INSTRUCTIONS.DEB,
FILEBEAT_INSTRUCTIONS.START.DEB
]
},
{
id: INSTRUCTION_VARIANT.RPM,
instructions: [
FILEBEAT_INSTRUCTIONS.PLUGINS.GEOIP_AND_UA,
FILEBEAT_INSTRUCTIONS.INSTALL.RPM,
FILEBEAT_INSTRUCTIONS.CONFIG.RPM,
ENABLE_INSTRUCTIONS.RPM,
FILEBEAT_INSTRUCTIONS.START.RPM
]
},
{
id: INSTRUCTION_VARIANT.WINDOWS,
instructions: [
FILEBEAT_INSTRUCTIONS.PLUGINS.GEOIP_AND_UA,
FILEBEAT_INSTRUCTIONS.INSTALL.WINDOWS,
FILEBEAT_INSTRUCTIONS.CONFIG.WINDOWS,
ENABLE_INSTRUCTIONS.WINDOWS,
FILEBEAT_INSTRUCTIONS.START.WINDOWS
]
}
]
}
]
};

View file

@ -0,0 +1,61 @@
import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant';
import { FILEBEAT_INSTRUCTIONS } from '../../../common/tutorials/filebeat_instructions';
import {
TRYCLOUD_OPTION1,
TRYCLOUD_OPTION2
} from '../../../common/tutorials/onprem_cloud_instructions';
import { ENABLE_INSTRUCTIONS } from './enable';
export const ON_PREM_ELASTIC_CLOUD_INSTRUCTIONS = {
instructionSets: [
{
title: 'Getting Started',
instructionVariants: [
{
id: INSTRUCTION_VARIANT.OSX,
instructions: [
TRYCLOUD_OPTION1,
TRYCLOUD_OPTION2,
FILEBEAT_INSTRUCTIONS.INSTALL.OSX,
FILEBEAT_INSTRUCTIONS.CONFIG.OSX,
ENABLE_INSTRUCTIONS.OSX,
FILEBEAT_INSTRUCTIONS.START.OSX
]
},
{
id: INSTRUCTION_VARIANT.DEB,
instructions: [
TRYCLOUD_OPTION1,
TRYCLOUD_OPTION2,
FILEBEAT_INSTRUCTIONS.INSTALL.DEB,
FILEBEAT_INSTRUCTIONS.CONFIG.DEB,
ENABLE_INSTRUCTIONS.DEB,
FILEBEAT_INSTRUCTIONS.START.DEB
]
},
{
id: INSTRUCTION_VARIANT.RPM,
instructions: [
TRYCLOUD_OPTION1,
TRYCLOUD_OPTION2,
FILEBEAT_INSTRUCTIONS.INSTALL.RPM,
FILEBEAT_INSTRUCTIONS.CONFIG.RPM,
ENABLE_INSTRUCTIONS.RPM,
FILEBEAT_INSTRUCTIONS.START.RPM
]
},
{
id: INSTRUCTION_VARIANT.WINDOWS,
instructions: [
TRYCLOUD_OPTION1,
TRYCLOUD_OPTION2,
FILEBEAT_INSTRUCTIONS.INSTALL.WINDOWS,
FILEBEAT_INSTRUCTIONS.CONFIG.WINDOWS,
ENABLE_INSTRUCTIONS.WINDOWS,
FILEBEAT_INSTRUCTIONS.START.WINDOWS
]
}
]
}
]
};

View file

@ -0,0 +1,50 @@
import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant';
import { METRICBEAT_INSTRUCTIONS } from '../../../common/tutorials/metricbeat_instructions';
import { METRICBEAT_CLOUD_INSTRUCTIONS } from '../../../common/tutorials/metricbeat_cloud_instructions';
import { ENABLE_INSTRUCTIONS } from './enable';
export const ELASTIC_CLOUD_INSTRUCTIONS = {
instructionSets: [
{
title: 'Getting Started',
instructionVariants: [
{
id: INSTRUCTION_VARIANT.OSX,
instructions: [
METRICBEAT_INSTRUCTIONS.INSTALL.OSX,
METRICBEAT_CLOUD_INSTRUCTIONS.CONFIG.OSX,
ENABLE_INSTRUCTIONS.OSX,
METRICBEAT_INSTRUCTIONS.START.OSX
]
},
{
id: INSTRUCTION_VARIANT.DEB,
instructions: [
METRICBEAT_INSTRUCTIONS.INSTALL.DEB,
METRICBEAT_CLOUD_INSTRUCTIONS.CONFIG.DEB,
ENABLE_INSTRUCTIONS.DEB,
METRICBEAT_INSTRUCTIONS.START.DEB
]
},
{
id: INSTRUCTION_VARIANT.RPM,
instructions: [
METRICBEAT_INSTRUCTIONS.INSTALL.RPM,
METRICBEAT_CLOUD_INSTRUCTIONS.CONFIG.RPM,
ENABLE_INSTRUCTIONS.RPM,
METRICBEAT_INSTRUCTIONS.START.RPM
]
},
{
id: INSTRUCTION_VARIANT.WINDOWS,
instructions: [
METRICBEAT_INSTRUCTIONS.INSTALL.WINDOWS,
METRICBEAT_CLOUD_INSTRUCTIONS.CONFIG.WINDOWS,
ENABLE_INSTRUCTIONS.WINDOWS,
METRICBEAT_INSTRUCTIONS.START.WINDOWS
]
}
]
}
]
};

View file

@ -0,0 +1,32 @@
export const ENABLE_INSTRUCTIONS = {
OSX: {
title: 'Enable and configure the apache module',
textPre: 'From the installation directory, run:',
commands: [
'./metricbeat modules enable apache',
],
textPost: 'Modify the settings in the `modules.d/apache.yml` file.'
},
DEB: {
title: 'Enable and configure the apache module',
commands: [
'sudo metricbeat modules enable apache',
],
textPost: 'Modify the settings in the `/etc/metricbeat/modules.d/apache.yml` file.'
},
RPM: {
title: 'Enable and configure the apache module',
commands: [
'sudo metricbeat modules enable apache',
],
textPost: 'Modify the settings in the `/etc/metricbeat/modules.d/apache.yml` file.'
},
WINDOWS: {
title: 'Enable and configure the apache module',
textPre: 'From the `C:\\Program Files\\Metricbeat` folder, run:',
commands: [
'PS C:\\Program Files\\Metricbeat> metricbeat.exe modules enable apache',
],
textPost: 'Modify the settings in the `modules.d/apache.yml` file.'
}
};

View file

@ -0,0 +1,34 @@
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { ON_PREM_INSTRUCTIONS } from './on_prem';
import { ELASTIC_CLOUD_INSTRUCTIONS } from './elastic_cloud';
import { ON_PREM_ELASTIC_CLOUD_INSTRUCTIONS } from './on_prem_elastic_cloud';
export function apacheMetricsSpecProvider() {
return {
id: 'apacheMetrics',
name: 'Apache metrics',
category: TUTORIAL_CATEGORY.METRICS,
shortDescription: 'Fetches internal metrics from the Apache 2 HTTP server.',
longDescription: 'The `apache` Metricbeat module fetches internal metrics from the Apache 2 HTTP server.' +
' [Learn more]({config.docs.beats.metricbeat}/metricbeat-module-apache.html)' +
' about the apache module.',
//iconPath: '', TODO
artifacts: {
dashboards: [
{
title: 'Metricbeat-Apache-HTTPD-server-status',
linkLabel: 'Apache metrics dashboard',
isOverview: true
}
],
exportedFields: {
documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-apache.html'
}
},
completionTimeMinutes: 10,
previewImagePath: '/plugins/kibana/home/tutorial_resources/apache_metrics/screenshot.png',
onPrem: ON_PREM_INSTRUCTIONS,
elasticCloud: ELASTIC_CLOUD_INSTRUCTIONS,
onPremElasticCloud: ON_PREM_ELASTIC_CLOUD_INSTRUCTIONS
};
}

View file

@ -0,0 +1,49 @@
import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant';
import { METRICBEAT_INSTRUCTIONS } from '../../../common/tutorials/metricbeat_instructions';
import { ENABLE_INSTRUCTIONS } from './enable';
export const ON_PREM_INSTRUCTIONS = {
instructionSets: [
{
title: 'Getting Started',
instructionVariants: [
{
id: INSTRUCTION_VARIANT.OSX,
instructions: [
METRICBEAT_INSTRUCTIONS.INSTALL.OSX,
METRICBEAT_INSTRUCTIONS.CONFIG.OSX,
ENABLE_INSTRUCTIONS.OSX,
METRICBEAT_INSTRUCTIONS.START.OSX
]
},
{
id: INSTRUCTION_VARIANT.DEB,
instructions: [
METRICBEAT_INSTRUCTIONS.INSTALL.DEB,
METRICBEAT_INSTRUCTIONS.CONFIG.DEB,
ENABLE_INSTRUCTIONS.DEB,
METRICBEAT_INSTRUCTIONS.START.DEB
]
},
{
id: INSTRUCTION_VARIANT.RPM,
instructions: [
METRICBEAT_INSTRUCTIONS.INSTALL.RPM,
METRICBEAT_INSTRUCTIONS.CONFIG.RPM,
ENABLE_INSTRUCTIONS.RPM,
METRICBEAT_INSTRUCTIONS.START.RPM
]
},
{
id: INSTRUCTION_VARIANT.WINDOWS,
instructions: [
METRICBEAT_INSTRUCTIONS.INSTALL.WINDOWS,
METRICBEAT_INSTRUCTIONS.CONFIG.WINDOWS,
ENABLE_INSTRUCTIONS.WINDOWS,
METRICBEAT_INSTRUCTIONS.START.WINDOWS
]
}
]
}
]
};

View file

@ -0,0 +1,61 @@
import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant';
import { METRICBEAT_INSTRUCTIONS } from '../../../common/tutorials/metricbeat_instructions';
import {
TRYCLOUD_OPTION1,
TRYCLOUD_OPTION2
} from '../../../common/tutorials/onprem_cloud_instructions';
import { ENABLE_INSTRUCTIONS } from './enable';
export const ON_PREM_ELASTIC_CLOUD_INSTRUCTIONS = {
instructionSets: [
{
title: 'Getting Started',
instructionVariants: [
{
id: INSTRUCTION_VARIANT.OSX,
instructions: [
TRYCLOUD_OPTION1,
TRYCLOUD_OPTION2,
METRICBEAT_INSTRUCTIONS.INSTALL.OSX,
METRICBEAT_INSTRUCTIONS.CONFIG.OSX,
ENABLE_INSTRUCTIONS.OSX,
METRICBEAT_INSTRUCTIONS.START.OSX
]
},
{
id: INSTRUCTION_VARIANT.DEB,
instructions: [
TRYCLOUD_OPTION1,
TRYCLOUD_OPTION2,
METRICBEAT_INSTRUCTIONS.INSTALL.DEB,
METRICBEAT_INSTRUCTIONS.CONFIG.DEB,
ENABLE_INSTRUCTIONS.DEB,
METRICBEAT_INSTRUCTIONS.START.DEB
]
},
{
id: INSTRUCTION_VARIANT.RPM,
instructions: [
TRYCLOUD_OPTION1,
TRYCLOUD_OPTION2,
METRICBEAT_INSTRUCTIONS.INSTALL.RPM,
METRICBEAT_INSTRUCTIONS.CONFIG.RPM,
ENABLE_INSTRUCTIONS.RPM,
METRICBEAT_INSTRUCTIONS.START.RPM
]
},
{
id: INSTRUCTION_VARIANT.WINDOWS,
instructions: [
TRYCLOUD_OPTION1,
TRYCLOUD_OPTION2,
METRICBEAT_INSTRUCTIONS.INSTALL.WINDOWS,
METRICBEAT_INSTRUCTIONS.CONFIG.WINDOWS,
ENABLE_INSTRUCTIONS.WINDOWS,
METRICBEAT_INSTRUCTIONS.START.WINDOWS
]
}
]
}
]
};

View file

@ -0,0 +1,50 @@
import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant';
import { FILEBEAT_INSTRUCTIONS } from '../../../common/tutorials/filebeat_instructions';
import { FILEBEAT_CLOUD_INSTRUCTIONS } from '../../../common/tutorials/filebeat_cloud_instructions';
import { ENABLE_INSTRUCTIONS } from './enable';
export const ELASTIC_CLOUD_INSTRUCTIONS = {
instructionSets: [
{
title: 'Getting Started',
instructionVariants: [
{
id: INSTRUCTION_VARIANT.OSX,
instructions: [
FILEBEAT_INSTRUCTIONS.INSTALL.OSX,
FILEBEAT_CLOUD_INSTRUCTIONS.CONFIG.OSX,
ENABLE_INSTRUCTIONS.OSX,
FILEBEAT_INSTRUCTIONS.START.OSX
]
},
{
id: INSTRUCTION_VARIANT.DEB,
instructions: [
FILEBEAT_INSTRUCTIONS.INSTALL.DEB,
FILEBEAT_CLOUD_INSTRUCTIONS.CONFIG.DEB,
ENABLE_INSTRUCTIONS.DEB,
FILEBEAT_INSTRUCTIONS.START.DEB
]
},
{
id: INSTRUCTION_VARIANT.RPM,
instructions: [
FILEBEAT_INSTRUCTIONS.INSTALL.RPM,
FILEBEAT_CLOUD_INSTRUCTIONS.CONFIG.RPM,
ENABLE_INSTRUCTIONS.RPM,
FILEBEAT_INSTRUCTIONS.START.RPM
]
},
{
id: INSTRUCTION_VARIANT.WINDOWS,
instructions: [
FILEBEAT_INSTRUCTIONS.INSTALL.WINDOWS,
FILEBEAT_CLOUD_INSTRUCTIONS.CONFIG.WINDOWS,
ENABLE_INSTRUCTIONS.WINDOWS,
FILEBEAT_INSTRUCTIONS.START.WINDOWS
]
}
]
}
]
};

View file

@ -0,0 +1,32 @@
export const ENABLE_INSTRUCTIONS = {
OSX: {
title: 'Enable and configure the mysql module',
textPre: 'From the installation directory, run:',
commands: [
'./filebeat modules enable mysql',
],
textPost: 'Modify the settings in the `modules.d/mysql.yml` file.'
},
DEB: {
title: 'Enable and configure the mysql module',
commands: [
'sudo filebeat modules enable mysql',
],
textPost: 'Modify the settings in the `/etc/filebeat/modules.d/mysql.yml` file.'
},
RPM: {
title: 'Enable and configure the mysql module',
commands: [
'sudo filebeat modules enable mysql',
],
textPost: 'Modify the settings in the `/etc/filebeat/modules.d/mysql.yml` file.'
},
WINDOWS: {
title: 'Enable and configure the mysql module',
textPre: 'From the `C:\\Program Files\\Filebeat` folder, run:',
commands: [
'PS C:\\Program Files\\Filebeat> filebeat.exe modules enable mysql',
],
textPost: 'Modify the settings in the `modules.d/mysql.yml` file.'
}
};

View file

@ -0,0 +1,34 @@
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { ON_PREM_INSTRUCTIONS } from './on_prem';
import { ELASTIC_CLOUD_INSTRUCTIONS } from './elastic_cloud';
import { ON_PREM_ELASTIC_CLOUD_INSTRUCTIONS } from './on_prem_elastic_cloud';
export function mysqlLogsSpecProvider() {
return {
id: 'mysqlLogs',
name: 'MySQL logs',
category: TUTORIAL_CATEGORY.LOGGING,
shortDescription: 'Collect and parse error and slow logs created by MySQL.',
longDescription: 'The `mysql` Filebeat module parses error and slow logs created by MySQL.' +
' [Learn more]({config.docs.beats.filebeat}/filebeat-module-mysql.html)' +
' about the `mysql` module.',
//iconPath: '', TODO
artifacts: {
dashboards: [
{
title: 'Filebeat-MySQL-Dashboard',
linkLabel: 'MySQL logs dashboard',
isOverview: true
}
],
exportedFields: {
documentationUrl: '{config.docs.beats.filebeat}/exported-fields-mysql.html'
}
},
completionTimeMinutes: 10,
previewImagePath: '/plugins/kibana/home/tutorial_resources/mysql_logs/screenshot.png',
onPrem: ON_PREM_INSTRUCTIONS,
elasticCloud: ELASTIC_CLOUD_INSTRUCTIONS,
onPremElasticCloud: ON_PREM_ELASTIC_CLOUD_INSTRUCTIONS
};
}

View file

@ -0,0 +1,49 @@
import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant';
import { FILEBEAT_INSTRUCTIONS } from '../../../common/tutorials/filebeat_instructions';
import { ENABLE_INSTRUCTIONS } from './enable';
export const ON_PREM_INSTRUCTIONS = {
instructionSets: [
{
title: 'Getting Started',
instructionVariants: [
{
id: INSTRUCTION_VARIANT.OSX,
instructions: [
FILEBEAT_INSTRUCTIONS.INSTALL.OSX,
FILEBEAT_INSTRUCTIONS.CONFIG.OSX,
ENABLE_INSTRUCTIONS.OSX,
FILEBEAT_INSTRUCTIONS.START.OSX
]
},
{
id: INSTRUCTION_VARIANT.DEB,
instructions: [
FILEBEAT_INSTRUCTIONS.INSTALL.DEB,
FILEBEAT_INSTRUCTIONS.CONFIG.DEB,
ENABLE_INSTRUCTIONS.DEB,
FILEBEAT_INSTRUCTIONS.START.DEB
]
},
{
id: INSTRUCTION_VARIANT.RPM,
instructions: [
FILEBEAT_INSTRUCTIONS.INSTALL.RPM,
FILEBEAT_INSTRUCTIONS.CONFIG.RPM,
ENABLE_INSTRUCTIONS.RPM,
FILEBEAT_INSTRUCTIONS.START.RPM
]
},
{
id: INSTRUCTION_VARIANT.WINDOWS,
instructions: [
FILEBEAT_INSTRUCTIONS.INSTALL.WINDOWS,
FILEBEAT_INSTRUCTIONS.CONFIG.WINDOWS,
ENABLE_INSTRUCTIONS.WINDOWS,
FILEBEAT_INSTRUCTIONS.START.WINDOWS
]
}
]
}
]
};

View file

@ -0,0 +1,61 @@
import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant';
import { FILEBEAT_INSTRUCTIONS } from '../../../common/tutorials/filebeat_instructions';
import {
TRYCLOUD_OPTION1,
TRYCLOUD_OPTION2
} from '../../../common/tutorials/onprem_cloud_instructions';
import { ENABLE_INSTRUCTIONS } from './enable';
export const ON_PREM_ELASTIC_CLOUD_INSTRUCTIONS = {
instructionSets: [
{
title: 'Getting Started',
instructionVariants: [
{
id: INSTRUCTION_VARIANT.OSX,
instructions: [
TRYCLOUD_OPTION1,
TRYCLOUD_OPTION2,
FILEBEAT_INSTRUCTIONS.INSTALL.OSX,
FILEBEAT_INSTRUCTIONS.CONFIG.OSX,
ENABLE_INSTRUCTIONS.OSX,
FILEBEAT_INSTRUCTIONS.START.OSX
]
},
{
id: INSTRUCTION_VARIANT.DEB,
instructions: [
TRYCLOUD_OPTION1,
TRYCLOUD_OPTION2,
FILEBEAT_INSTRUCTIONS.INSTALL.DEB,
FILEBEAT_INSTRUCTIONS.CONFIG.DEB,
ENABLE_INSTRUCTIONS.DEB,
FILEBEAT_INSTRUCTIONS.START.DEB
]
},
{
id: INSTRUCTION_VARIANT.RPM,
instructions: [
TRYCLOUD_OPTION1,
TRYCLOUD_OPTION2,
FILEBEAT_INSTRUCTIONS.INSTALL.RPM,
FILEBEAT_INSTRUCTIONS.CONFIG.RPM,
ENABLE_INSTRUCTIONS.RPM,
FILEBEAT_INSTRUCTIONS.START.RPM
]
},
{
id: INSTRUCTION_VARIANT.WINDOWS,
instructions: [
TRYCLOUD_OPTION1,
TRYCLOUD_OPTION2,
FILEBEAT_INSTRUCTIONS.INSTALL.WINDOWS,
FILEBEAT_INSTRUCTIONS.CONFIG.WINDOWS,
ENABLE_INSTRUCTIONS.WINDOWS,
FILEBEAT_INSTRUCTIONS.START.WINDOWS
]
}
]
}
]
};

View file

@ -0,0 +1,50 @@
import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant';
import { METRICBEAT_INSTRUCTIONS } from '../../../common/tutorials/metricbeat_instructions';
import { METRICBEAT_CLOUD_INSTRUCTIONS } from '../../../common/tutorials/metricbeat_cloud_instructions';
import { ENABLE_INSTRUCTIONS } from './enable';
export const ELASTIC_CLOUD_INSTRUCTIONS = {
instructionSets: [
{
title: 'Getting Started',
instructionVariants: [
{
id: INSTRUCTION_VARIANT.OSX,
instructions: [
METRICBEAT_INSTRUCTIONS.INSTALL.OSX,
METRICBEAT_CLOUD_INSTRUCTIONS.CONFIG.OSX,
ENABLE_INSTRUCTIONS.OSX,
METRICBEAT_INSTRUCTIONS.START.OSX
]
},
{
id: INSTRUCTION_VARIANT.DEB,
instructions: [
METRICBEAT_INSTRUCTIONS.INSTALL.DEB,
METRICBEAT_CLOUD_INSTRUCTIONS.CONFIG.DEB,
ENABLE_INSTRUCTIONS.DEB,
METRICBEAT_INSTRUCTIONS.START.DEB
]
},
{
id: INSTRUCTION_VARIANT.RPM,
instructions: [
METRICBEAT_INSTRUCTIONS.INSTALL.RPM,
METRICBEAT_CLOUD_INSTRUCTIONS.CONFIG.RPM,
ENABLE_INSTRUCTIONS.RPM,
METRICBEAT_INSTRUCTIONS.START.RPM
]
},
{
id: INSTRUCTION_VARIANT.WINDOWS,
instructions: [
METRICBEAT_INSTRUCTIONS.INSTALL.WINDOWS,
METRICBEAT_CLOUD_INSTRUCTIONS.CONFIG.WINDOWS,
ENABLE_INSTRUCTIONS.WINDOWS,
METRICBEAT_INSTRUCTIONS.START.WINDOWS
]
}
]
}
]
};

View file

@ -0,0 +1,32 @@
export const ENABLE_INSTRUCTIONS = {
OSX: {
title: 'Enable and configure the mysql module',
textPre: 'From the installation directory, run:',
commands: [
'./metricbeat modules enable mysql',
],
textPost: 'Modify the settings in the `modules.d/mysql.yml` file.'
},
DEB: {
title: 'Enable and configure the mysql module',
commands: [
'sudo metricbeat modules enable mysql',
],
textPost: 'Modify the settings in the `/etc/metricbeat/modules.d/mysql.yml` file.'
},
RPM: {
title: 'Enable and configure the mysql module',
commands: [
'sudo metricbeat modules enable mysql',
],
textPost: 'Modify the settings in the `/etc/metricbeat/modules.d/mysql.yml` file.'
},
WINDOWS: {
title: 'Enable and configure the mysql module',
textPre: 'From the `C:\\Program Files\\Metricbeat` folder, run:',
commands: [
'PS C:\\Program Files\\Metricbeat> metricbeat.exe modules enable mysql',
],
textPost: 'Modify the settings in the `modules.d/mysql.yml` file.'
}
};

View file

@ -0,0 +1,34 @@
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { ON_PREM_INSTRUCTIONS } from './on_prem';
import { ELASTIC_CLOUD_INSTRUCTIONS } from './elastic_cloud';
import { ON_PREM_ELASTIC_CLOUD_INSTRUCTIONS } from './on_prem_elastic_cloud';
export function mysqlMetricsSpecProvider() {
return {
id: 'mysqlMetrics',
name: 'MySQL metrics',
category: TUTORIAL_CATEGORY.METRICS,
shortDescription: 'Fetches internal metrics from MySQL.',
longDescription: 'The `mysql` Metricbeat module fetches internal metrics from the MySQL server.' +
' [Learn more]({config.docs.beats.metricbeat}/metricbeat-module-mysql.html)' +
' about the mysql module.',
//iconPath: '', TODO
artifacts: {
dashboards: [
{
title: '66881e90-0006-11e7-bf7f-c9acc3d3e306',
linkLabel: 'MySQL metrics dashboard',
isOverview: true
}
],
exportedFields: {
documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-mysql.html'
}
},
completionTimeMinutes: 10,
previewImagePath: '/plugins/kibana/home/tutorial_resources/mysql_metrics/screenshot.png',
onPrem: ON_PREM_INSTRUCTIONS,
elasticCloud: ELASTIC_CLOUD_INSTRUCTIONS,
onPremElasticCloud: ON_PREM_ELASTIC_CLOUD_INSTRUCTIONS
};
}

View file

@ -0,0 +1,49 @@
import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant';
import { METRICBEAT_INSTRUCTIONS } from '../../../common/tutorials/metricbeat_instructions';
import { ENABLE_INSTRUCTIONS } from './enable';
export const ON_PREM_INSTRUCTIONS = {
instructionSets: [
{
title: 'Getting Started',
instructionVariants: [
{
id: INSTRUCTION_VARIANT.OSX,
instructions: [
METRICBEAT_INSTRUCTIONS.INSTALL.OSX,
METRICBEAT_INSTRUCTIONS.CONFIG.OSX,
ENABLE_INSTRUCTIONS.OSX,
METRICBEAT_INSTRUCTIONS.START.OSX
]
},
{
id: INSTRUCTION_VARIANT.DEB,
instructions: [
METRICBEAT_INSTRUCTIONS.INSTALL.DEB,
METRICBEAT_INSTRUCTIONS.CONFIG.DEB,
ENABLE_INSTRUCTIONS.DEB,
METRICBEAT_INSTRUCTIONS.START.DEB
]
},
{
id: INSTRUCTION_VARIANT.RPM,
instructions: [
METRICBEAT_INSTRUCTIONS.INSTALL.RPM,
METRICBEAT_INSTRUCTIONS.CONFIG.RPM,
ENABLE_INSTRUCTIONS.RPM,
METRICBEAT_INSTRUCTIONS.START.RPM
]
},
{
id: INSTRUCTION_VARIANT.WINDOWS,
instructions: [
METRICBEAT_INSTRUCTIONS.INSTALL.WINDOWS,
METRICBEAT_INSTRUCTIONS.CONFIG.WINDOWS,
ENABLE_INSTRUCTIONS.WINDOWS,
METRICBEAT_INSTRUCTIONS.START.WINDOWS
]
}
]
}
]
};

View file

@ -0,0 +1,61 @@
import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant';
import { METRICBEAT_INSTRUCTIONS } from '../../../common/tutorials/metricbeat_instructions';
import {
TRYCLOUD_OPTION1,
TRYCLOUD_OPTION2
} from '../../../common/tutorials/onprem_cloud_instructions';
import { ENABLE_INSTRUCTIONS } from './enable';
export const ON_PREM_ELASTIC_CLOUD_INSTRUCTIONS = {
instructionSets: [
{
title: 'Getting Started',
instructionVariants: [
{
id: INSTRUCTION_VARIANT.OSX,
instructions: [
TRYCLOUD_OPTION1,
TRYCLOUD_OPTION2,
METRICBEAT_INSTRUCTIONS.INSTALL.OSX,
METRICBEAT_INSTRUCTIONS.CONFIG.OSX,
ENABLE_INSTRUCTIONS.OSX,
METRICBEAT_INSTRUCTIONS.START.OSX
]
},
{
id: INSTRUCTION_VARIANT.DEB,
instructions: [
TRYCLOUD_OPTION1,
TRYCLOUD_OPTION2,
METRICBEAT_INSTRUCTIONS.INSTALL.DEB,
METRICBEAT_INSTRUCTIONS.CONFIG.DEB,
ENABLE_INSTRUCTIONS.DEB,
METRICBEAT_INSTRUCTIONS.START.DEB
]
},
{
id: INSTRUCTION_VARIANT.RPM,
instructions: [
TRYCLOUD_OPTION1,
TRYCLOUD_OPTION2,
METRICBEAT_INSTRUCTIONS.INSTALL.RPM,
METRICBEAT_INSTRUCTIONS.CONFIG.RPM,
ENABLE_INSTRUCTIONS.RPM,
METRICBEAT_INSTRUCTIONS.START.RPM
]
},
{
id: INSTRUCTION_VARIANT.WINDOWS,
instructions: [
TRYCLOUD_OPTION1,
TRYCLOUD_OPTION2,
METRICBEAT_INSTRUCTIONS.INSTALL.WINDOWS,
METRICBEAT_INSTRUCTIONS.CONFIG.WINDOWS,
ENABLE_INSTRUCTIONS.WINDOWS,
METRICBEAT_INSTRUCTIONS.START.WINDOWS
]
}
]
}
]
};

View file

@ -0,0 +1,91 @@
export const COMMON_NETFLOW_INSTRUCTIONS = {
CONFIG: {
ON_PREM: {
OSX: [
{
title: 'Edit the configuration',
textPre: 'In the Logstash installation directory, modify `config/logstash.yml` to set the'
+ ' configuration parameters for the Netflow module.',
commands: [
'modules:',
' - name: netflow',
' var.input.udp.port: <udp_port_for_receving_netflow_data>',
' var.elasticsearch.hosts: [ "<es_url>" ]',
' var.kibana.host: "<kibana_hostname>:<kibana_port>"'
]
}
],
WINDOWS: [
{
title: 'Edit the configuration',
textPre: 'While in the Logstash install directory, modify `config\\logstash.yml` to set the'
+ ' configuration parameters for the Netflow module:',
commands: [
'modules:',
' - name: netflow',
' var.input.udp.port: <udp_port_for_receving_netflow_data>',
' var.elasticsearch.hosts: [ "<es_url>" ]',
' var.kibana.host: "<kibana_hostname>:<kibana_port>"'
]
}
]
},
ELASTIC_CLOUD: {
OSX: [
{
title: 'Edit the configuration',
textPre: 'In the Logstash installation directory, modify `config/logstash.yml` to set the'
+ ' configuration parameters for the Netflow module.',
commands: [
'modules:',
' - name: netflow',
' var.input.udp.port: <udp_port_for_receving_netflow_data>',
' cloud.id: "{config.cloud.id}"',
' cloud.auth: "elastic:<password>"'
],
textPost: 'Where `<password>` is the password of the `elastic` user.'
}
],
WINDOWS: [
{
title: 'Edit the configuration',
textPre: 'While in the Logstash install directory, modify `config\\logstash.yml` to set the'
+ ' configuration parameters for the Netflow module:',
commands: [
'modules:',
' - name: netflow',
' var.input.udp.port: <udp_port_for_receving_netflow_data>',
' cloud.id: "{config.cloud.id}"',
' cloud.auth: "elastic:<password>"'
]
}
]
}
},
SETUP: {
OSX: [
{
title: 'Run the Netflow module',
textPre: 'In the Logstash installation directory, run the following command to set up the Netflow module.',
commands: [
'./bin/logstash --modules netflow --setup',
],
textPost: 'The `--setup` option creates a `netflow-*` index pattern in Elasticsearch and imports' +
' Kibana dashboards and visualizations. Omit this option for subsequent runs of the module to avoid' +
' overwriting existing Kibana dashboards.'
}
],
WINDOWS: [
{
title: 'Set up and run the Netflow module',
textPre: 'In the Logstash install directory, run the following command to set up the Netflow module.',
commands: [
'bin\\logstash --modules netflow --setup',
],
textPost: 'The `--setup` option creates a `netflow-*` index pattern in Elasticsearch and imports' +
' Kibana dashboards and visualizations. Omit this option for subsequent runs of the module to avoid' +
' overwriting existing Kibana dashboards.'
}
]
}
};

View file

@ -0,0 +1,30 @@
import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant';
import { LOGSTASH_INSTRUCTIONS } from '../../../common/tutorials/logstash_instructions';
import { COMMON_NETFLOW_INSTRUCTIONS } from './common_instructions';
// TODO: compare with onPremElasticCloud and onPrem scenarios and extract out common bits
export const ELASTIC_CLOUD_INSTRUCTIONS = {
instructionSets: [
{
title: 'Getting Started',
instructionVariants: [
{
id: INSTRUCTION_VARIANT.OSX,
instructions: [
...LOGSTASH_INSTRUCTIONS.INSTALL.OSX,
...COMMON_NETFLOW_INSTRUCTIONS.CONFIG.ELASTIC_CLOUD.OSX,
...COMMON_NETFLOW_INSTRUCTIONS.SETUP.OSX
]
},
{
id: INSTRUCTION_VARIANT.WINDOWS,
instructions: [
...LOGSTASH_INSTRUCTIONS.INSTALL.WINDOWS,
...COMMON_NETFLOW_INSTRUCTIONS.CONFIG.ELASTIC_CLOUD.WINDOWS,
...COMMON_NETFLOW_INSTRUCTIONS.SETUP.WINDOWS
]
}
]
}
]
};

View file

@ -0,0 +1,23 @@
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { ON_PREM_INSTRUCTIONS } from './on_prem';
import { ELASTIC_CLOUD_INSTRUCTIONS } from './elastic_cloud';
import { ON_PREM_ELASTIC_CLOUD_INSTRUCTIONS } from './on_prem_elastic_cloud';
export function netflowSpecProvider() {
return {
id: 'netflow',
name: 'Netflow',
category: TUTORIAL_CATEGORY.SECURITY,
shortDescription: 'Collect Netflow records sent by a Netflow exporter',
longDescription: 'The Logstash Netflow module simplifies the collection, normalization, and visualization of network flow data. ' +
'With a single command, the module parses network flow data, indexes the events into Elasticsearch, and installs a suite of Kibana ' +
'dashboards to get you exploring your data immediately. Logstash modules support Netflow Version 5 and 9. [Learn more]' +
'({config.docs.logstash}/netflow-module.html) about the Netflow module',
//iconPath: '', TODO
completionTimeMinutes: 10,
//previewImagePath: 'kibana-apache.png', TODO
onPrem: ON_PREM_INSTRUCTIONS,
elasticCloud: ELASTIC_CLOUD_INSTRUCTIONS,
onPremElasticCloud: ON_PREM_ELASTIC_CLOUD_INSTRUCTIONS
};
}

View file

@ -0,0 +1,30 @@
import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant';
import { LOGSTASH_INSTRUCTIONS } from '../../../common/tutorials/logstash_instructions';
import { COMMON_NETFLOW_INSTRUCTIONS } from './common_instructions';
// TODO: compare with onPremElasticCloud and elasticCloud scenarios and extract out common bits
export const ON_PREM_INSTRUCTIONS = {
instructionSets: [
{
title: 'Getting Started',
instructionVariants: [
{
id: INSTRUCTION_VARIANT.OSX,
instructions: [
...LOGSTASH_INSTRUCTIONS.INSTALL.OSX,
...COMMON_NETFLOW_INSTRUCTIONS.CONFIG.ON_PREM.OSX,
...COMMON_NETFLOW_INSTRUCTIONS.SETUP.OSX
]
},
{
id: INSTRUCTION_VARIANT.WINDOWS,
instructions: [
...LOGSTASH_INSTRUCTIONS.INSTALL.WINDOWS,
...COMMON_NETFLOW_INSTRUCTIONS.CONFIG.ON_PREM.WINDOWS,
...COMMON_NETFLOW_INSTRUCTIONS.SETUP.WINDOWS
]
}
]
}
]
};

View file

@ -0,0 +1,38 @@
import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant';
import { LOGSTASH_INSTRUCTIONS } from '../../../common/tutorials/logstash_instructions';
import {
TRYCLOUD_OPTION1,
TRYCLOUD_OPTION2
} from '../../../common/tutorials/onprem_cloud_instructions';
import { COMMON_NETFLOW_INSTRUCTIONS } from './common_instructions';
// TODO: compare with onPrem and elasticCloud scenarios and extract out common bits
export const ON_PREM_ELASTIC_CLOUD_INSTRUCTIONS = {
instructionSets: [
{
title: 'Getting Started',
instructionVariants: [
{
id: INSTRUCTION_VARIANT.OSX,
instructions: [
TRYCLOUD_OPTION1,
TRYCLOUD_OPTION2,
...LOGSTASH_INSTRUCTIONS.INSTALL.OSX,
...COMMON_NETFLOW_INSTRUCTIONS.CONFIG.ON_PREM.OSX,
...COMMON_NETFLOW_INSTRUCTIONS.SETUP.OSX
]
},
{
id: INSTRUCTION_VARIANT.WINDOWS,
instructions: [
TRYCLOUD_OPTION1,
TRYCLOUD_OPTION2,
...LOGSTASH_INSTRUCTIONS.INSTALL.WINDOWS,
...COMMON_NETFLOW_INSTRUCTIONS.CONFIG.ON_PREM.WINDOWS,
...COMMON_NETFLOW_INSTRUCTIONS.SETUP.WINDOWS
]
}
]
}
]
};

View file

@ -0,0 +1,50 @@
import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant';
import { FILEBEAT_INSTRUCTIONS } from '../../../common/tutorials/filebeat_instructions';
import { FILEBEAT_CLOUD_INSTRUCTIONS } from '../../../common/tutorials/filebeat_cloud_instructions';
import { ENABLE_INSTRUCTIONS } from './enable';
export const ELASTIC_CLOUD_INSTRUCTIONS = {
instructionSets: [
{
title: 'Getting Started',
instructionVariants: [
{
id: INSTRUCTION_VARIANT.OSX,
instructions: [
FILEBEAT_INSTRUCTIONS.INSTALL.OSX,
FILEBEAT_CLOUD_INSTRUCTIONS.CONFIG.OSX,
ENABLE_INSTRUCTIONS.OSX,
FILEBEAT_INSTRUCTIONS.START.OSX
]
},
{
id: INSTRUCTION_VARIANT.DEB,
instructions: [
FILEBEAT_INSTRUCTIONS.INSTALL.DEB,
FILEBEAT_CLOUD_INSTRUCTIONS.CONFIG.DEB,
ENABLE_INSTRUCTIONS.DEB,
FILEBEAT_INSTRUCTIONS.START.DEB
]
},
{
id: INSTRUCTION_VARIANT.RPM,
instructions: [
FILEBEAT_INSTRUCTIONS.INSTALL.RPM,
FILEBEAT_CLOUD_INSTRUCTIONS.CONFIG.RPM,
ENABLE_INSTRUCTIONS.RPM,
FILEBEAT_INSTRUCTIONS.START.RPM
]
},
{
id: INSTRUCTION_VARIANT.WINDOWS,
instructions: [
FILEBEAT_INSTRUCTIONS.INSTALL.WINDOWS,
FILEBEAT_CLOUD_INSTRUCTIONS.CONFIG.WINDOWS,
ENABLE_INSTRUCTIONS.WINDOWS,
FILEBEAT_INSTRUCTIONS.START.WINDOWS
]
}
]
}
]
};

View file

@ -0,0 +1,32 @@
export const ENABLE_INSTRUCTIONS = {
OSX: {
title: 'Enable and configure the nginx module',
textPre: 'From the installation directory, run:',
commands: [
'./filebeat modules enable nginx',
],
textPost: 'Modify the settings in the `modules.d/nginx.yml` file.'
},
DEB: {
title: 'Enable and configure the nginx module',
commands: [
'sudo filebeat modules enable nginx',
],
textPost: 'Modify the settings in the `/etc/filebeat/modules.d/nginx.yml` file.'
},
RPM: {
title: 'Enable and configure the nginx module',
commands: [
'sudo filebeat modules enable nginx',
],
textPost: 'Modify the settings in the `/etc/filebeat/modules.d/nginx.yml` file.'
},
WINDOWS: {
title: 'Enable and configure the nginx module',
textPre: 'From the `C:\\Program Files\\Filebeat` folder, run:',
commands: [
'PS C:\\Program Files\\Filebeat> filebeat.exe modules enable nginx',
],
textPost: 'Modify the settings in the `modules.d/nginx.yml` file.'
}
};

View file

@ -0,0 +1,34 @@
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { ON_PREM_INSTRUCTIONS } from './on_prem';
import { ELASTIC_CLOUD_INSTRUCTIONS } from './elastic_cloud';
import { ON_PREM_ELASTIC_CLOUD_INSTRUCTIONS } from './on_prem_elastic_cloud';
export function nginxLogsSpecProvider() {
return {
id: 'nginxLogs',
name: 'Nginx logs',
category: TUTORIAL_CATEGORY.LOGGING,
shortDescription: 'Collect and parse access and error logs created by the Nginx HTTP server.',
longDescription: 'The `nginx` Filebeat module parses access and error logs created by the Nginx HTTP server.' +
' [Learn more]({config.docs.beats.filebeat}/filebeat-module-nginx.html)' +
' about the nginx module.',
//iconPath: '', TODO
artifacts: {
dashboards: [
{
title: '55a9e6e0-a29e-11e7-928f-5dbe6f6f5519',
linkLabel: 'Nginx logs dashboard',
isOverview: true
}
],
exportedFields: {
documentationUrl: '{config.docs.beats.filebeat}/exported-fields-nginx.html'
}
},
completionTimeMinutes: 10,
previewImagePath: '/plugins/kibana/home/tutorial_resources/nginx_logs/screenshot.png',
onPrem: ON_PREM_INSTRUCTIONS,
elasticCloud: ELASTIC_CLOUD_INSTRUCTIONS,
onPremElasticCloud: ON_PREM_ELASTIC_CLOUD_INSTRUCTIONS
};
}

View file

@ -0,0 +1,53 @@
import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant';
import { FILEBEAT_INSTRUCTIONS } from '../../../common/tutorials/filebeat_instructions';
import { ENABLE_INSTRUCTIONS } from './enable';
export const ON_PREM_INSTRUCTIONS = {
instructionSets: [
{
title: 'Getting Started',
instructionVariants: [
{
id: INSTRUCTION_VARIANT.OSX,
instructions: [
FILEBEAT_INSTRUCTIONS.PLUGINS.GEOIP_AND_UA,
FILEBEAT_INSTRUCTIONS.INSTALL.OSX,
FILEBEAT_INSTRUCTIONS.CONFIG.OSX,
ENABLE_INSTRUCTIONS.OSX,
FILEBEAT_INSTRUCTIONS.START.OSX
]
},
{
id: INSTRUCTION_VARIANT.DEB,
instructions: [
FILEBEAT_INSTRUCTIONS.PLUGINS.GEOIP_AND_UA,
FILEBEAT_INSTRUCTIONS.INSTALL.DEB,
FILEBEAT_INSTRUCTIONS.CONFIG.DEB,
ENABLE_INSTRUCTIONS.DEB,
FILEBEAT_INSTRUCTIONS.START.DEB
]
},
{
id: INSTRUCTION_VARIANT.RPM,
instructions: [
FILEBEAT_INSTRUCTIONS.PLUGINS.GEOIP_AND_UA,
FILEBEAT_INSTRUCTIONS.INSTALL.RPM,
FILEBEAT_INSTRUCTIONS.CONFIG.RPM,
ENABLE_INSTRUCTIONS.RPM,
FILEBEAT_INSTRUCTIONS.START.RPM
]
},
{
id: INSTRUCTION_VARIANT.WINDOWS,
instructions: [
FILEBEAT_INSTRUCTIONS.PLUGINS.GEOIP_AND_UA,
FILEBEAT_INSTRUCTIONS.INSTALL.WINDOWS,
FILEBEAT_INSTRUCTIONS.CONFIG.WINDOWS,
ENABLE_INSTRUCTIONS.WINDOWS,
FILEBEAT_INSTRUCTIONS.START.WINDOWS
]
}
]
}
]
};

View file

@ -0,0 +1,61 @@
import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant';
import { FILEBEAT_INSTRUCTIONS } from '../../../common/tutorials/filebeat_instructions';
import {
TRYCLOUD_OPTION1,
TRYCLOUD_OPTION2
} from '../../../common/tutorials/onprem_cloud_instructions';
import { ENABLE_INSTRUCTIONS } from './enable';
export const ON_PREM_ELASTIC_CLOUD_INSTRUCTIONS = {
instructionSets: [
{
title: 'Getting Started',
instructionVariants: [
{
id: INSTRUCTION_VARIANT.OSX,
instructions: [
TRYCLOUD_OPTION1,
TRYCLOUD_OPTION2,
FILEBEAT_INSTRUCTIONS.INSTALL.OSX,
FILEBEAT_INSTRUCTIONS.CONFIG.OSX,
ENABLE_INSTRUCTIONS.OSX,
FILEBEAT_INSTRUCTIONS.START.OSX
]
},
{
id: INSTRUCTION_VARIANT.DEB,
instructions: [
TRYCLOUD_OPTION1,
TRYCLOUD_OPTION2,
FILEBEAT_INSTRUCTIONS.INSTALL.DEB,
FILEBEAT_INSTRUCTIONS.CONFIG.DEB,
ENABLE_INSTRUCTIONS.DEB,
FILEBEAT_INSTRUCTIONS.START.DEB
]
},
{
id: INSTRUCTION_VARIANT.RPM,
instructions: [
TRYCLOUD_OPTION1,
TRYCLOUD_OPTION2,
FILEBEAT_INSTRUCTIONS.INSTALL.RPM,
FILEBEAT_INSTRUCTIONS.CONFIG.RPM,
ENABLE_INSTRUCTIONS.RPM,
FILEBEAT_INSTRUCTIONS.START.RPM
]
},
{
id: INSTRUCTION_VARIANT.WINDOWS,
instructions: [
TRYCLOUD_OPTION1,
TRYCLOUD_OPTION2,
FILEBEAT_INSTRUCTIONS.INSTALL.WINDOWS,
FILEBEAT_INSTRUCTIONS.CONFIG.WINDOWS,
ENABLE_INSTRUCTIONS.WINDOWS,
FILEBEAT_INSTRUCTIONS.START.WINDOWS
]
}
]
}
]
};

View file

@ -0,0 +1,50 @@
import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant';
import { METRICBEAT_INSTRUCTIONS } from '../../../common/tutorials/metricbeat_instructions';
import { METRICBEAT_CLOUD_INSTRUCTIONS } from '../../../common/tutorials/metricbeat_cloud_instructions';
import { ENABLE_INSTRUCTIONS } from './enable';
export const ELASTIC_CLOUD_INSTRUCTIONS = {
instructionSets: [
{
title: 'Getting Started',
instructionVariants: [
{
id: INSTRUCTION_VARIANT.OSX,
instructions: [
METRICBEAT_INSTRUCTIONS.INSTALL.OSX,
METRICBEAT_CLOUD_INSTRUCTIONS.CONFIG.OSX,
ENABLE_INSTRUCTIONS.OSX,
METRICBEAT_INSTRUCTIONS.START.OSX
]
},
{
id: INSTRUCTION_VARIANT.DEB,
instructions: [
METRICBEAT_INSTRUCTIONS.INSTALL.DEB,
METRICBEAT_CLOUD_INSTRUCTIONS.CONFIG.DEB,
ENABLE_INSTRUCTIONS.DEB,
METRICBEAT_INSTRUCTIONS.START.DEB
]
},
{
id: INSTRUCTION_VARIANT.RPM,
instructions: [
METRICBEAT_INSTRUCTIONS.INSTALL.RPM,
METRICBEAT_CLOUD_INSTRUCTIONS.CONFIG.RPM,
ENABLE_INSTRUCTIONS.RPM,
METRICBEAT_INSTRUCTIONS.START.RPM
]
},
{
id: INSTRUCTION_VARIANT.WINDOWS,
instructions: [
METRICBEAT_INSTRUCTIONS.INSTALL.WINDOWS,
METRICBEAT_CLOUD_INSTRUCTIONS.CONFIG.WINDOWS,
ENABLE_INSTRUCTIONS.WINDOWS,
METRICBEAT_INSTRUCTIONS.START.WINDOWS
]
}
]
}
]
};

View file

@ -0,0 +1,32 @@
export const ENABLE_INSTRUCTIONS = {
OSX: {
title: 'Enable and configure the nginx module',
textPre: 'From the installation directory, run:',
commands: [
'./metricbeat modules enable nginx',
],
textPost: 'Modify the settings in the `modules.d/nginx.yml` file.'
},
DEB: {
title: 'Enable and configure the nginx module',
commands: [
'sudo metricbeat modules enable nginx',
],
textPost: 'Modify the settings in the `/etc/metricbeat/modules.d/nginx.yml` file.'
},
RPM: {
title: 'Enable and configure the nginx module',
commands: [
'sudo metricbeat modules enable nginx',
],
textPost: 'Modify the settings in the `/etc/metricbeat/modules.d/nginx.yml` file.'
},
WINDOWS: {
title: 'Enable and configure the nginx module',
textPre: 'From the `C:\\Program Files\\Metricbeat` folder, run:',
commands: [
'PS C:\\Program Files\\Metricbeat> metricbeat.exe modules enable nginx',
],
textPost: 'Modify the settings in the `modules.d/nginx.yml` file.'
}
};

View file

@ -0,0 +1,37 @@
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { ON_PREM_INSTRUCTIONS } from './on_prem';
import { ELASTIC_CLOUD_INSTRUCTIONS } from './elastic_cloud';
import { ON_PREM_ELASTIC_CLOUD_INSTRUCTIONS } from './on_prem_elastic_cloud';
export function nginxMetricsSpecProvider() {
return {
id: 'nginxMetrics',
name: 'Nginx metrics',
category: TUTORIAL_CATEGORY.METRICS,
shortDescription: 'Fetches internal metrics from the Nginx HTTP server.',
longDescription: 'The `nginx` Metricbeat module fetches internal metrics from the Nginx HTTP server.' +
' The module scrapes the server status data from the web page generated by the' +
' [ngx_http_stub_status_module](http://nginx.org/en/docs/http/ngx_http_stub_status_module.html)' +
' module, which needs to be enabled in you Nginx installation.' +
' [Learn more]({config.docs.beats.metricbeat}/metricbeat-module-nginx.html)' +
' about the nginx module.',
//iconPath: '', TODO
artifacts: {
dashboards: [
{
title: '023d2930-f1a5-11e7-a9ef-93c69af7b129',
linkLabel: 'Nginx metrics dashboard',
isOverview: true
}
],
exportedFields: {
documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-nginx.html'
}
},
completionTimeMinutes: 10,
previewImagePath: '/plugins/kibana/home/tutorial_resources/nginx_metrics/screenshot.png',
onPrem: ON_PREM_INSTRUCTIONS,
elasticCloud: ELASTIC_CLOUD_INSTRUCTIONS,
onPremElasticCloud: ON_PREM_ELASTIC_CLOUD_INSTRUCTIONS
};
}

View file

@ -0,0 +1,49 @@
import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant';
import { METRICBEAT_INSTRUCTIONS } from '../../../common/tutorials/metricbeat_instructions';
import { ENABLE_INSTRUCTIONS } from './enable';
export const ON_PREM_INSTRUCTIONS = {
instructionSets: [
{
title: 'Getting Started',
instructionVariants: [
{
id: INSTRUCTION_VARIANT.OSX,
instructions: [
METRICBEAT_INSTRUCTIONS.INSTALL.OSX,
METRICBEAT_INSTRUCTIONS.CONFIG.OSX,
ENABLE_INSTRUCTIONS.OSX,
METRICBEAT_INSTRUCTIONS.START.OSX
]
},
{
id: INSTRUCTION_VARIANT.DEB,
instructions: [
METRICBEAT_INSTRUCTIONS.INSTALL.DEB,
METRICBEAT_INSTRUCTIONS.CONFIG.DEB,
ENABLE_INSTRUCTIONS.DEB,
METRICBEAT_INSTRUCTIONS.START.DEB
]
},
{
id: INSTRUCTION_VARIANT.RPM,
instructions: [
METRICBEAT_INSTRUCTIONS.INSTALL.RPM,
METRICBEAT_INSTRUCTIONS.CONFIG.RPM,
ENABLE_INSTRUCTIONS.RPM,
METRICBEAT_INSTRUCTIONS.START.RPM
]
},
{
id: INSTRUCTION_VARIANT.WINDOWS,
instructions: [
METRICBEAT_INSTRUCTIONS.INSTALL.WINDOWS,
METRICBEAT_INSTRUCTIONS.CONFIG.WINDOWS,
ENABLE_INSTRUCTIONS.WINDOWS,
METRICBEAT_INSTRUCTIONS.START.WINDOWS
]
}
]
}
]
};

View file

@ -0,0 +1,61 @@
import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant';
import { METRICBEAT_INSTRUCTIONS } from '../../../common/tutorials/metricbeat_instructions';
import {
TRYCLOUD_OPTION1,
TRYCLOUD_OPTION2
} from '../../../common/tutorials/onprem_cloud_instructions';
import { ENABLE_INSTRUCTIONS } from './enable';
export const ON_PREM_ELASTIC_CLOUD_INSTRUCTIONS = {
instructionSets: [
{
title: 'Getting Started',
instructionVariants: [
{
id: INSTRUCTION_VARIANT.OSX,
instructions: [
TRYCLOUD_OPTION1,
TRYCLOUD_OPTION2,
METRICBEAT_INSTRUCTIONS.INSTALL.OSX,
METRICBEAT_INSTRUCTIONS.CONFIG.OSX,
ENABLE_INSTRUCTIONS.OSX,
METRICBEAT_INSTRUCTIONS.START.OSX
]
},
{
id: INSTRUCTION_VARIANT.DEB,
instructions: [
TRYCLOUD_OPTION1,
TRYCLOUD_OPTION2,
METRICBEAT_INSTRUCTIONS.INSTALL.DEB,
METRICBEAT_INSTRUCTIONS.CONFIG.DEB,
ENABLE_INSTRUCTIONS.DEB,
METRICBEAT_INSTRUCTIONS.START.DEB
]
},
{
id: INSTRUCTION_VARIANT.RPM,
instructions: [
TRYCLOUD_OPTION1,
TRYCLOUD_OPTION2,
METRICBEAT_INSTRUCTIONS.INSTALL.RPM,
METRICBEAT_INSTRUCTIONS.CONFIG.RPM,
ENABLE_INSTRUCTIONS.RPM,
METRICBEAT_INSTRUCTIONS.START.RPM
]
},
{
id: INSTRUCTION_VARIANT.WINDOWS,
instructions: [
TRYCLOUD_OPTION1,
TRYCLOUD_OPTION2,
METRICBEAT_INSTRUCTIONS.INSTALL.WINDOWS,
METRICBEAT_INSTRUCTIONS.CONFIG.WINDOWS,
ENABLE_INSTRUCTIONS.WINDOWS,
METRICBEAT_INSTRUCTIONS.START.WINDOWS
]
}
]
}
]
};

View file

@ -0,0 +1,21 @@
import { systemLogsSpecProvider } from './system_logs';
import { systemMetricsSpecProvider } from './system_metrics';
import { apacheLogsSpecProvider } from './apache_logs';
import { apacheMetricsSpecProvider } from './apache_metrics';
import { nginxLogsSpecProvider } from './nginx_logs';
import { nginxMetricsSpecProvider } from './nginx_metrics';
import { mysqlLogsSpecProvider } from './mysql_logs';
import { mysqlMetricsSpecProvider } from './mysql_metrics';
import { netflowSpecProvider } from './netflow';
export function registerTutorials(server) {
server.registerTutorial(systemLogsSpecProvider);
server.registerTutorial(systemMetricsSpecProvider);
server.registerTutorial(apacheLogsSpecProvider);
server.registerTutorial(apacheMetricsSpecProvider);
server.registerTutorial(nginxLogsSpecProvider);
server.registerTutorial(nginxMetricsSpecProvider);
server.registerTutorial(mysqlLogsSpecProvider);
server.registerTutorial(mysqlMetricsSpecProvider);
server.registerTutorial(netflowSpecProvider);
}

View file

@ -0,0 +1,50 @@
import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant';
import { FILEBEAT_INSTRUCTIONS } from '../../../common/tutorials/filebeat_instructions';
import { FILEBEAT_CLOUD_INSTRUCTIONS } from '../../../common/tutorials/filebeat_cloud_instructions';
import { ENABLE_INSTRUCTIONS } from './enable';
export const ELASTIC_CLOUD_INSTRUCTIONS = {
instructionSets: [
{
title: 'Getting Started',
instructionVariants: [
{
id: INSTRUCTION_VARIANT.OSX,
instructions: [
FILEBEAT_INSTRUCTIONS.INSTALL.OSX,
FILEBEAT_CLOUD_INSTRUCTIONS.CONFIG.OSX,
ENABLE_INSTRUCTIONS.OSX,
FILEBEAT_INSTRUCTIONS.START.OSX
]
},
{
id: INSTRUCTION_VARIANT.DEB,
instructions: [
FILEBEAT_INSTRUCTIONS.INSTALL.DEB,
FILEBEAT_CLOUD_INSTRUCTIONS.CONFIG.DEB,
ENABLE_INSTRUCTIONS.DEB,
FILEBEAT_INSTRUCTIONS.START.DEB
]
},
{
id: INSTRUCTION_VARIANT.RPM,
instructions: [
FILEBEAT_INSTRUCTIONS.INSTALL.RPM,
FILEBEAT_CLOUD_INSTRUCTIONS.CONFIG.RPM,
ENABLE_INSTRUCTIONS.RPM,
FILEBEAT_INSTRUCTIONS.START.RPM
]
},
{
id: INSTRUCTION_VARIANT.WINDOWS,
instructions: [
FILEBEAT_INSTRUCTIONS.INSTALL.WINDOWS,
FILEBEAT_CLOUD_INSTRUCTIONS.CONFIG.WINDOWS,
ENABLE_INSTRUCTIONS.WINDOWS,
FILEBEAT_INSTRUCTIONS.START.WINDOWS
]
}
]
}
]
};

View file

@ -0,0 +1,32 @@
export const ENABLE_INSTRUCTIONS = {
OSX: {
title: 'Enable and configure the system module',
textPre: 'From the installation directory, run:',
commands: [
'./filebeat modules enable system',
],
textPost: 'Modify the settings in the `modules.d/system.yml` file.'
},
DEB: {
title: 'Enable and configure the system module',
commands: [
'sudo filebeat modules enable system',
],
textPost: 'Modify the settings in the `/etc/filebeat/modules.d/system.yml` file.'
},
RPM: {
title: 'Enable and configure the system module',
commands: [
'sudo filebeat modules enable system',
],
textPost: 'Modify the settings in the `/etc/filebeat/modules.d/system.yml` file.'
},
WINDOWS: {
title: 'Enable and configure the system module',
textPre: 'From the `C:\\Program Files\\Filebeat` folder, run:',
commands: [
'PS C:\\Program Files\\Filebeat> filebeat.exe modules enable system',
],
textPost: 'Modify the settings in the `modules.d/system.yml` file.'
}
};

View file

@ -0,0 +1,35 @@
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { ON_PREM_INSTRUCTIONS } from './on_prem';
import { ELASTIC_CLOUD_INSTRUCTIONS } from './elastic_cloud';
import { ON_PREM_ELASTIC_CLOUD_INSTRUCTIONS } from './on_prem_elastic_cloud';
export function systemLogsSpecProvider() {
return {
id: 'systemLogs',
name: 'System logs',
category: TUTORIAL_CATEGORY.LOGGING,
shortDescription: 'Collect and parse logs written by the local Syslog server.',
longDescription: 'The `system` Filebeat module collects and parses logs created by the system logging service of common ' +
' Unix/Linux based distributions. This module is not available on Windows.' +
' [Learn more]({config.docs.beats.filebeat}/filebeat-module-system.html)' +
' about the `system` module.',
//iconPath: '', TODO
artifacts: {
dashboards: [
{
title: 'Filebeat-syslog-dashboard',
linkLabel: 'System logs dashboard',
isOverview: true
}
],
exportedFields: {
documentationUrl: '{config.docs.beats.filebeat}/exported-fields-system.html'
}
},
completionTimeMinutes: 10,
previewImagePath: '/plugins/kibana/home/tutorial_resources/system_logs/screenshot.png',
onPrem: ON_PREM_INSTRUCTIONS,
elasticCloud: ELASTIC_CLOUD_INSTRUCTIONS,
onPremElasticCloud: ON_PREM_ELASTIC_CLOUD_INSTRUCTIONS
};
}

View file

@ -0,0 +1,53 @@
import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant';
import { FILEBEAT_INSTRUCTIONS } from '../../../common/tutorials/filebeat_instructions';
import { ENABLE_INSTRUCTIONS } from './enable';
export const ON_PREM_INSTRUCTIONS = {
instructionSets: [
{
title: 'Getting Started',
instructionVariants: [
{
id: INSTRUCTION_VARIANT.OSX,
instructions: [
FILEBEAT_INSTRUCTIONS.PLUGINS.GEOIP,
FILEBEAT_INSTRUCTIONS.INSTALL.OSX,
FILEBEAT_INSTRUCTIONS.CONFIG.OSX,
ENABLE_INSTRUCTIONS.OSX,
FILEBEAT_INSTRUCTIONS.START.OSX
]
},
{
id: INSTRUCTION_VARIANT.DEB,
instructions: [
FILEBEAT_INSTRUCTIONS.PLUGINS.GEOIP,
FILEBEAT_INSTRUCTIONS.INSTALL.DEB,
FILEBEAT_INSTRUCTIONS.CONFIG.DEB,
ENABLE_INSTRUCTIONS.DEB,
FILEBEAT_INSTRUCTIONS.START.DEB
]
},
{
id: INSTRUCTION_VARIANT.RPM,
instructions: [
FILEBEAT_INSTRUCTIONS.PLUGINS.GEOIP,
FILEBEAT_INSTRUCTIONS.INSTALL.RPM,
FILEBEAT_INSTRUCTIONS.CONFIG.RPM,
ENABLE_INSTRUCTIONS.RPM,
FILEBEAT_INSTRUCTIONS.START.RPM
]
},
{
id: INSTRUCTION_VARIANT.WINDOWS,
instructions: [
FILEBEAT_INSTRUCTIONS.PLUGINS.GEOIP,
FILEBEAT_INSTRUCTIONS.INSTALL.WINDOWS,
FILEBEAT_INSTRUCTIONS.CONFIG.WINDOWS,
ENABLE_INSTRUCTIONS.WINDOWS,
FILEBEAT_INSTRUCTIONS.START.WINDOWS
]
}
]
}
]
};

View file

@ -0,0 +1,61 @@
import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant';
import { FILEBEAT_INSTRUCTIONS } from '../../../common/tutorials/filebeat_instructions';
import {
TRYCLOUD_OPTION1,
TRYCLOUD_OPTION2
} from '../../../common/tutorials/onprem_cloud_instructions';
import { ENABLE_INSTRUCTIONS } from './enable';
export const ON_PREM_ELASTIC_CLOUD_INSTRUCTIONS = {
instructionSets: [
{
title: 'Getting Started',
instructionVariants: [
{
id: INSTRUCTION_VARIANT.OSX,
instructions: [
TRYCLOUD_OPTION1,
TRYCLOUD_OPTION2,
FILEBEAT_INSTRUCTIONS.INSTALL.OSX,
FILEBEAT_INSTRUCTIONS.CONFIG.OSX,
ENABLE_INSTRUCTIONS.OSX,
FILEBEAT_INSTRUCTIONS.START.OSX
]
},
{
id: INSTRUCTION_VARIANT.DEB,
instructions: [
TRYCLOUD_OPTION1,
TRYCLOUD_OPTION2,
FILEBEAT_INSTRUCTIONS.INSTALL.DEB,
FILEBEAT_INSTRUCTIONS.CONFIG.DEB,
ENABLE_INSTRUCTIONS.DEB,
FILEBEAT_INSTRUCTIONS.START.DEB
]
},
{
id: INSTRUCTION_VARIANT.RPM,
instructions: [
TRYCLOUD_OPTION1,
TRYCLOUD_OPTION2,
FILEBEAT_INSTRUCTIONS.INSTALL.RPM,
FILEBEAT_INSTRUCTIONS.CONFIG.RPM,
ENABLE_INSTRUCTIONS.RPM,
FILEBEAT_INSTRUCTIONS.START.RPM
]
},
{
id: INSTRUCTION_VARIANT.WINDOWS,
instructions: [
TRYCLOUD_OPTION1,
TRYCLOUD_OPTION2,
FILEBEAT_INSTRUCTIONS.INSTALL.WINDOWS,
FILEBEAT_INSTRUCTIONS.CONFIG.WINDOWS,
ENABLE_INSTRUCTIONS.WINDOWS,
FILEBEAT_INSTRUCTIONS.START.WINDOWS
]
}
]
}
]
};

View file

@ -0,0 +1,50 @@
import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant';
import { METRICBEAT_INSTRUCTIONS } from '../../../common/tutorials/metricbeat_instructions';
import { METRICBEAT_CLOUD_INSTRUCTIONS } from '../../../common/tutorials/metricbeat_cloud_instructions';
import { ENABLE_INSTRUCTIONS } from './enable';
export const ELASTIC_CLOUD_INSTRUCTIONS = {
instructionSets: [
{
title: 'Getting Started',
instructionVariants: [
{
id: INSTRUCTION_VARIANT.OSX,
instructions: [
METRICBEAT_INSTRUCTIONS.INSTALL.OSX,
METRICBEAT_CLOUD_INSTRUCTIONS.CONFIG.OSX,
ENABLE_INSTRUCTIONS.OSX,
METRICBEAT_INSTRUCTIONS.START.OSX
]
},
{
id: INSTRUCTION_VARIANT.DEB,
instructions: [
METRICBEAT_INSTRUCTIONS.INSTALL.DEB,
METRICBEAT_CLOUD_INSTRUCTIONS.CONFIG.DEB,
ENABLE_INSTRUCTIONS.DEB,
METRICBEAT_INSTRUCTIONS.START.DEB
]
},
{
id: INSTRUCTION_VARIANT.RPM,
instructions: [
METRICBEAT_INSTRUCTIONS.INSTALL.RPM,
METRICBEAT_CLOUD_INSTRUCTIONS.CONFIG.RPM,
ENABLE_INSTRUCTIONS.RPM,
METRICBEAT_INSTRUCTIONS.START.RPM
]
},
{
id: INSTRUCTION_VARIANT.WINDOWS,
instructions: [
METRICBEAT_INSTRUCTIONS.INSTALL.WINDOWS,
METRICBEAT_CLOUD_INSTRUCTIONS.CONFIG.WINDOWS,
ENABLE_INSTRUCTIONS.WINDOWS,
METRICBEAT_INSTRUCTIONS.START.WINDOWS
]
}
]
}
]
};

View file

@ -0,0 +1,32 @@
export const ENABLE_INSTRUCTIONS = {
OSX: {
title: 'Enable and configure the system module',
textPre: 'From the installation directory, run:',
commands: [
'./metricbeat modules enable system',
],
textPost: 'Modify the settings in the `modules.d/system.yml` file.'
},
DEB: {
title: 'Enable and configure the system module',
commands: [
'sudo metricbeat modules enable system',
],
textPost: 'Modify the settings in the `/etc/metricbeat/modules.d/system.yml` file.'
},
RPM: {
title: 'Enable and configure the system module',
commands: [
'sudo metricbeat modules enable system',
],
textPost: 'Modify the settings in the `/etc/metricbeat/modules.d/system.yml` file.'
},
WINDOWS: {
title: 'Enable and configure the system module',
textPre: 'From the `C:\\Program Files\\Metricbeat` folder, run:',
commands: [
'PS C:\\Program Files\\Metricbeat> metricbeat.exe modules enable system',
],
textPost: 'Modify the settings in the `modules.d/system.yml` file.'
}
};

View file

@ -0,0 +1,35 @@
import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category';
import { ON_PREM_INSTRUCTIONS } from './on_prem';
import { ELASTIC_CLOUD_INSTRUCTIONS } from './elastic_cloud';
import { ON_PREM_ELASTIC_CLOUD_INSTRUCTIONS } from './on_prem_elastic_cloud';
export function systemMetricsSpecProvider() {
return {
id: 'systemMetrics',
name: 'System metrics',
category: TUTORIAL_CATEGORY.METRICS,
shortDescription: 'Collects CPU, memory, network, and disk statistics from the host.',
longDescription: 'The `system` Metricbeat module collects CPU, memory, network, and disk statistics from the host.' +
' It collects system wide statistics as well as per process and per filesystem statistics.' +
' [Learn more]({config.docs.beats.metricbeat}/metricbeat-module-system.html)' +
' about the system module.',
//iconPath: '', TODO
artifacts: {
dashboards: [
{
title: 'Metricbeat-system-overview',
linkLabel: 'System metrics dashboard',
isOverview: true
}
],
exportedFields: {
documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-system.html'
}
},
completionTimeMinutes: 10,
previewImagePath: '/plugins/kibana/home/tutorial_resources/system_metrics/screenshot.png',
onPrem: ON_PREM_INSTRUCTIONS,
elasticCloud: ELASTIC_CLOUD_INSTRUCTIONS,
onPremElasticCloud: ON_PREM_ELASTIC_CLOUD_INSTRUCTIONS
};
}

View file

@ -0,0 +1,49 @@
import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant';
import { METRICBEAT_INSTRUCTIONS } from '../../../common/tutorials/metricbeat_instructions';
import { ENABLE_INSTRUCTIONS } from './enable';
export const ON_PREM_INSTRUCTIONS = {
instructionSets: [
{
title: 'Getting Started',
instructionVariants: [
{
id: INSTRUCTION_VARIANT.OSX,
instructions: [
METRICBEAT_INSTRUCTIONS.INSTALL.OSX,
METRICBEAT_INSTRUCTIONS.CONFIG.OSX,
ENABLE_INSTRUCTIONS.OSX,
METRICBEAT_INSTRUCTIONS.START.OSX
]
},
{
id: INSTRUCTION_VARIANT.DEB,
instructions: [
METRICBEAT_INSTRUCTIONS.INSTALL.DEB,
METRICBEAT_INSTRUCTIONS.CONFIG.DEB,
ENABLE_INSTRUCTIONS.DEB,
METRICBEAT_INSTRUCTIONS.START.DEB
]
},
{
id: INSTRUCTION_VARIANT.RPM,
instructions: [
METRICBEAT_INSTRUCTIONS.INSTALL.RPM,
METRICBEAT_INSTRUCTIONS.CONFIG.RPM,
ENABLE_INSTRUCTIONS.RPM,
METRICBEAT_INSTRUCTIONS.START.RPM
]
},
{
id: INSTRUCTION_VARIANT.WINDOWS,
instructions: [
METRICBEAT_INSTRUCTIONS.INSTALL.WINDOWS,
METRICBEAT_INSTRUCTIONS.CONFIG.WINDOWS,
ENABLE_INSTRUCTIONS.WINDOWS,
METRICBEAT_INSTRUCTIONS.START.WINDOWS
]
}
]
}
]
};

View file

@ -0,0 +1,61 @@
import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant';
import { METRICBEAT_INSTRUCTIONS } from '../../../common/tutorials/metricbeat_instructions';
import {
TRYCLOUD_OPTION1,
TRYCLOUD_OPTION2
} from '../../../common/tutorials/onprem_cloud_instructions';
import { ENABLE_INSTRUCTIONS } from './enable';
export const ON_PREM_ELASTIC_CLOUD_INSTRUCTIONS = {
instructionSets: [
{
title: 'Getting Started',
instructionVariants: [
{
id: INSTRUCTION_VARIANT.OSX,
instructions: [
TRYCLOUD_OPTION1,
TRYCLOUD_OPTION2,
METRICBEAT_INSTRUCTIONS.INSTALL.OSX,
METRICBEAT_INSTRUCTIONS.CONFIG.OSX,
ENABLE_INSTRUCTIONS.OSX,
METRICBEAT_INSTRUCTIONS.START.OSX
]
},
{
id: INSTRUCTION_VARIANT.DEB,
instructions: [
TRYCLOUD_OPTION1,
TRYCLOUD_OPTION2,
METRICBEAT_INSTRUCTIONS.INSTALL.DEB,
METRICBEAT_INSTRUCTIONS.CONFIG.DEB,
ENABLE_INSTRUCTIONS.DEB,
METRICBEAT_INSTRUCTIONS.START.DEB
]
},
{
id: INSTRUCTION_VARIANT.RPM,
instructions: [
TRYCLOUD_OPTION1,
TRYCLOUD_OPTION2,
METRICBEAT_INSTRUCTIONS.INSTALL.RPM,
METRICBEAT_INSTRUCTIONS.CONFIG.RPM,
ENABLE_INSTRUCTIONS.RPM,
METRICBEAT_INSTRUCTIONS.START.RPM
]
},
{
id: INSTRUCTION_VARIANT.WINDOWS,
instructions: [
TRYCLOUD_OPTION1,
TRYCLOUD_OPTION2,
METRICBEAT_INSTRUCTIONS.INSTALL.WINDOWS,
METRICBEAT_INSTRUCTIONS.CONFIG.WINDOWS,
ENABLE_INSTRUCTIONS.WINDOWS,
METRICBEAT_INSTRUCTIONS.START.WINDOWS
]
}
]
}
]
};

View file

@ -5,6 +5,7 @@ export const ELASTIC_WEBSITE_URL = 'https://www.elastic.co/';
export const documentationLinks = {
filebeat: {
base: `${ELASTIC_WEBSITE_URL}guide/en/beats/filebeat/${DOC_LINK_VERSION}`,
installation: `${ELASTIC_WEBSITE_URL}guide/en/beats/filebeat/${DOC_LINK_VERSION}/filebeat-installation.html`,
configuration: `${ELASTIC_WEBSITE_URL}guide/en/beats/filebeat/${DOC_LINK_VERSION}/filebeat-configuration.html`,
elasticsearchOutput: `${ELASTIC_WEBSITE_URL}guide/en/beats/filebeat/${DOC_LINK_VERSION}/elasticsearch-output.html`,
@ -13,6 +14,12 @@ export const documentationLinks = {
startup: `${ELASTIC_WEBSITE_URL}guide/en/beats/filebeat/${DOC_LINK_VERSION}/filebeat-starting.html`,
exportedFields: `${ELASTIC_WEBSITE_URL}guide/en/beats/filebeat/${DOC_LINK_VERSION}/exported-fields.html`
},
metricbeat: {
base: `${ELASTIC_WEBSITE_URL}guide/en/beats/metricbeat/${DOC_LINK_VERSION}`
},
logstash: {
base: `${ELASTIC_WEBSITE_URL}guide/en/logstash/${DOC_LINK_VERSION}`
},
scriptedFields: {
scriptFields: `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}/search-request-script-fields.html`,
scriptAggs: `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}/search-aggregations.html#_values_source`,

21
src/ui/tutorials_mixin.js Normal file
View file

@ -0,0 +1,21 @@
import _ from 'lodash';
import Joi from 'joi';
import { tutorialSchema } from '../core_plugins/kibana/common/tutorials/tutorial_schema';
export function tutorialsMixin(kbnServer, server) {
const tutorials = [];
server.decorate('server', 'getTutorials', () => {
return _.cloneDeep(tutorials);
});
server.decorate('server', 'registerTutorial', (specProvider) => {
const { error, value } = Joi.validate(specProvider(), tutorialSchema);
if (error) {
throw new Error(`Unable to register tutorial spec because its invalid. ${error}`);
}
tutorials.push(value);
});
}

Some files were not shown because too many files have changed in this diff Show more