From 0225a8c652822d1efbd1a446b1cd8a8b145a510e Mon Sep 17 00:00:00 2001 From: cauemarcondes Date: Fri, 18 Jun 2021 11:36:19 -0400 Subject: [PATCH 01/11] adding environment credencials --- .../components/tutorial/instruction.js | 10 +- .../components/tutorial/instruction_set.js | 3 + .../components/tutorial/tutorial.js | 1 + .../tutorial/config_agent/commands/django.ts | 72 ++++ .../tutorial/config_agent/commands/dotnet.ts | 16 + .../tutorial/config_agent/commands/flask.ts | 70 ++++ .../config_agent/commands/get_commands.ts | 44 +++ .../tutorial/config_agent/commands/go.ts | 58 +++ .../tutorial/config_agent/commands/java.ts | 14 + .../tutorial/config_agent/commands/node.ts | 57 +++ .../tutorial/config_agent/commands/php.ts | 11 + .../tutorial/config_agent/commands/rack.ts | 50 +++ .../tutorial/config_agent/commands/rails.ts | 22 ++ .../tutorial/config_agent/commands/rum.ts | 60 +++ .../shared/tutorial/config_agent/index.tsx | 211 ++++++++++ .../tutorial/config_agent/rum_script.tsx | 15 + .../shared/tutorial/copy_commands.tsx | 23 ++ x-pack/plugins/apm/public/plugin.ts | 10 + .../apm/server/lib/fleet/get_agents.ts | 34 ++ x-pack/plugins/apm/server/routes/fleet.ts | 70 +++- .../instructions/apm_agent_instructions.ts | 361 +----------------- x-pack/plugins/fleet/server/plugin.ts | 1 + x-pack/plugins/fleet/server/services/index.ts | 1 + 23 files changed, 859 insertions(+), 355 deletions(-) create mode 100644 x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/django.ts create mode 100644 x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/dotnet.ts create mode 100644 x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/flask.ts create mode 100644 x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/get_commands.ts create mode 100644 x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/go.ts create mode 100644 x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/java.ts create mode 100644 x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/node.ts create mode 100644 x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/php.ts create mode 100644 x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/rack.ts create mode 100644 x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/rails.ts create mode 100644 x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/rum.ts create mode 100644 x-pack/plugins/apm/public/components/shared/tutorial/config_agent/index.tsx create mode 100644 x-pack/plugins/apm/public/components/shared/tutorial/config_agent/rum_script.tsx create mode 100644 x-pack/plugins/apm/public/components/shared/tutorial/copy_commands.tsx create mode 100644 x-pack/plugins/apm/server/lib/fleet/get_agents.ts diff --git a/src/plugins/home/public/application/components/tutorial/instruction.js b/src/plugins/home/public/application/components/tutorial/instruction.js index 373f8c318a5048..61aeb221072154 100644 --- a/src/plugins/home/public/application/components/tutorial/instruction.js +++ b/src/plugins/home/public/application/components/tutorial/instruction.js @@ -31,6 +31,8 @@ export function Instruction({ textPre, replaceTemplateStrings, customComponentName, + variantId, + isCloudEnabled, }) { const { tutorialService, http, uiSettings, getBasePath } = getServices(); @@ -96,18 +98,20 @@ export function Instruction({ {commandBlock} - {post} - {LazyCustomComponent && ( }> )} + {post} + ); @@ -120,4 +124,6 @@ Instruction.propTypes = { textPre: PropTypes.string, replaceTemplateStrings: PropTypes.func.isRequired, customComponentName: PropTypes.string, + variantId: PropTypes.string, + isCloudEnabled: PropTypes.bool.isRequired, }; diff --git a/src/plugins/home/public/application/components/tutorial/instruction_set.js b/src/plugins/home/public/application/components/tutorial/instruction_set.js index da368120d493c8..08b55a527b3cf5 100644 --- a/src/plugins/home/public/application/components/tutorial/instruction_set.js +++ b/src/plugins/home/public/application/components/tutorial/instruction_set.js @@ -187,6 +187,8 @@ class InstructionSetUi extends React.Component { textPost={instruction.textPost} replaceTemplateStrings={this.props.replaceTemplateStrings} customComponentName={instruction.customComponentName} + variantId={instructionVariant.id} + isCloudEnabled={this.props.isCloudEnabled} /> ); return { @@ -320,6 +322,7 @@ InstructionSetUi.propTypes = { paramValues: PropTypes.object.isRequired, setParameter: PropTypes.func, replaceTemplateStrings: PropTypes.func.isRequired, + isCloudEnabled: PropTypes.bool.isRequired, }; export const InstructionSet = injectI18n(InstructionSetUi); diff --git a/src/plugins/home/public/application/components/tutorial/tutorial.js b/src/plugins/home/public/application/components/tutorial/tutorial.js index 92bbb92fa08507..52daa53d4585c8 100644 --- a/src/plugins/home/public/application/components/tutorial/tutorial.js +++ b/src/plugins/home/public/application/components/tutorial/tutorial.js @@ -301,6 +301,7 @@ class TutorialUi extends React.Component { setParameter={this.setParameter} replaceTemplateStrings={this.props.replaceTemplateStrings} key={index} + isCloudEnabled={this.props.isCloudEnabled} /> ); }); diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/django.ts b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/django.ts new file mode 100644 index 00000000000000..686fcd02765492 --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/django.ts @@ -0,0 +1,72 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; + +export const django = `# ${i18n.translate( + 'xpack.apm.tutorial.djangoClient.configure.commands.addAgentComment', + { + defaultMessage: 'Add the agent to the installed apps', + } +)} +INSTALLED_APPS = ( +'elasticapm.contrib.django', +# ... +) + +ELASTIC_APM = {curlyOpen} +# ${i18n.translate( + 'xpack.apm.tutorial.djangoClient.configure.commands.setRequiredServiceNameComment', + { + defaultMessage: 'Set the required service name. Allowed characters:', + } +)} +# ${i18n.translate( + 'xpack.apm.tutorial.djangoClient.configure.commands.allowedCharactersComment', + { + defaultMessage: 'a-z, A-Z, 0-9, -, _, and space', + } +)} +'SERVICE_NAME': '', + +# ${i18n.translate( + 'xpack.apm.tutorial.djangoClient.configure.commands.useIfApmServerRequiresTokenComment', + { + defaultMessage: 'Use if APM Server requires a secret token', + } +)} +'SECRET_TOKEN': '{{secretToken}}', + +# ${i18n.translate( + 'xpack.apm.tutorial.djangoClient.configure.commands.setCustomApmServerUrlComment', + { + defaultMessage: + 'Set the custom APM Server URL (default: {defaultApmServerUrl})', + values: { defaultApmServerUrl: 'http://localhost:8200' }, + } +)} +'SERVER_URL': '{{apmServerUrl}}', + +# ${i18n.translate( + 'xpack.apm.tutorial.djangoClient.configure.commands.setServiceEnvironmentComment', + { + defaultMessage: 'Set the service environment', + } +)} +'ENVIRONMENT': 'production', +{curlyClose} + +# ${i18n.translate( + 'xpack.apm.tutorial.djangoClient.configure.commands.addTracingMiddlewareComment', + { + defaultMessage: 'To send performance metrics, add our tracing middleware:', + } +)} +MIDDLEWARE = ( +'elasticapm.contrib.django.middleware.TracingMiddleware', +#... +)`; diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/dotnet.ts b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/dotnet.ts new file mode 100644 index 00000000000000..d11234e0b546c6 --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/dotnet.ts @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +// TODO: ${'http://localhost:8200'}' fallback server_url + +export const dotnet = `{ +"ElasticApm": { +"SecretToken": "{{secretToken}}", +"ServerUrls": "{{apmServerUrl}}", //Set custom APM Server URL (default: http://localhost:8200) +"ServiceName": "MyApp", //allowed characters: a-z, A-Z, 0-9, -, _, and space. Default is the entry assembly of the application +"Environment": "production", // Set the service environment +} +}`; diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/flask.ts b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/flask.ts new file mode 100644 index 00000000000000..d97b5e71723280 --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/flask.ts @@ -0,0 +1,70 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; + +export const flask = `# ${i18n.translate( + 'xpack.apm.tutorial.flaskClient.configure.commands.initializeUsingEnvironmentVariablesComment', + { + defaultMessage: 'initialize using environment variables', + } +)} +from elasticapm.contrib.flask import ElasticAPM +app = Flask(__name__) +apm = ElasticAPM(app) + +# ${i18n.translate( + 'xpack.apm.tutorial.flaskClient.configure.commands.configureElasticApmComment', + { + defaultMessage: + "or configure to use ELASTIC_APM in your application's settings", + } +)} +from elasticapm.contrib.flask import ElasticAPM +app.config['ELASTIC_APM'] = {curlyOpen} +# ${i18n.translate( + 'xpack.apm.tutorial.flaskClient.configure.commands.setRequiredServiceNameComment', + { + defaultMessage: 'Set the required service name. Allowed characters:', + } +)} +# ${i18n.translate( + 'xpack.apm.tutorial.flaskClient.configure.commands.allowedCharactersComment', + { + defaultMessage: 'a-z, A-Z, 0-9, -, _, and space', + } +)} +'SERVICE_NAME': '', + +# ${i18n.translate( + 'xpack.apm.tutorial.flaskClient.configure.commands.useIfApmServerRequiresTokenComment', + { + defaultMessage: 'Use if APM Server requires a secret token', + } +)} +'SECRET_TOKEN': '{{secretToken}}', + +# ${i18n.translate( + 'xpack.apm.tutorial.flaskClient.configure.commands.setCustomApmServerUrlComment', + { + defaultMessage: + 'Set the custom APM Server URL (default: {defaultApmServerUrl})', + values: { defaultApmServerUrl: 'http://localhost:8200' }, + } +)} +'SERVER_URL': '{{apmServerUrl}}', + +# ${i18n.translate( + 'xpack.apm.tutorial.flaskClient.configure.commands.setServiceEnvironmentComment', + { + defaultMessage: 'Set the service environment', + } +)} +'ENVIRONMENT': 'production', +{curlyClose} + +apm = ElasticAPM(app)`; diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/get_commands.ts b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/get_commands.ts new file mode 100644 index 00000000000000..5fa869b019f246 --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/get_commands.ts @@ -0,0 +1,44 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import Mustache from 'mustache'; +import { java } from './java'; +import { node } from './node'; +import { django } from './django'; +import { flask } from './flask'; +import { rails } from './rails'; +import { rack } from './rack'; +import { go } from './go'; +import { dotnet } from './dotnet'; +import { php } from './php'; +import { rum, rumScript } from './rum'; + +const commands: Record = { + java, + node, + django, + flask, + rails, + rack, + go, + dotnet, + php, + js: rum, + js_script: rumScript, +}; + +export function getCommands({ + variantId, + environmentDetails, +}: { + variantId: string; + environmentDetails: { + apmServerUrl?: string; + secretToken?: string; + }; +}) { + return Mustache.render(commands[variantId], environmentDetails); +} diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/go.ts b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/go.ts new file mode 100644 index 00000000000000..a1878dc382764f --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/go.ts @@ -0,0 +1,58 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; + +export const go = `# ${i18n.translate( + 'xpack.apm.tutorial.goClient.configure.commands.initializeUsingEnvironmentVariablesComment', + { + defaultMessage: 'Initialize using environment variables:', + } +)} + +# ${i18n.translate( + 'xpack.apm.tutorial.goClient.configure.commands.setServiceNameComment', + { + defaultMessage: + 'Set the service name. Allowed characters: # a-z, A-Z, 0-9, -, _, and space.', + } +)} +# ${i18n.translate( + 'xpack.apm.tutorial.goClient.configure.commands.usedExecutableNameComment', + { + defaultMessage: + 'If ELASTIC_APM_SERVICE_NAME is not specified, the executable name will be used.', + } +)} +export ELASTIC_APM_SERVICE_NAME= + +# ${i18n.translate( + 'xpack.apm.tutorial.goClient.configure.commands.setCustomApmServerUrlComment', + { + defaultMessage: + 'Set custom APM Server URL (default: {defaultApmServerUrl})', + values: { defaultApmServerUrl: 'http://localhost:8200' }, + } +)} +export ELASTIC_APM_SERVER_URL={{apmServerUrl}} + +# ${i18n.translate( + 'xpack.apm.tutorial.goClient.configure.commands.useIfApmRequiresTokenComment', + { + defaultMessage: 'Use if APM Server requires a secret token', + } +)} +export ELASTIC_APM_SECRET_TOKEN={{secretToken}} + +# ${i18n.translate( + 'xpack.apm.tutorial.goClient.configure.commands.setServiceEnvironment', + { + defaultMessage: 'Set the service environment', + } +)} +export ELASTIC_APM_ENVIRONMENT= +`; diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/java.ts b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/java.ts new file mode 100644 index 00000000000000..2d8c38d73966c1 --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/java.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export const java = `java -javaagent:/path/to/elastic-apm-agent-.jar \\ +-Delastic.apm.service_name=my-application \\ +-Delastic.apm.server_urls= {{apmServerUrl}} \\ +-Delastic.apm.secret_token= {{secretToken}} \\ +-Delastic.apm.environment=production \\ +-Delastic.apm.application_packages=org.example \\ +-jar my-application.jar`; diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/node.ts b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/node.ts new file mode 100644 index 00000000000000..553d861cfb0c30 --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/node.ts @@ -0,0 +1,57 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { i18n } from '@kbn/i18n'; + +export const node = `// ${i18n.translate( + 'xpack.apm.tutorial.nodeClient.configure.commands.addThisToTheFileTopComment', + { + defaultMessage: + 'Add this to the VERY top of the first file loaded in your app', + } +)} +var apm = require('elastic-apm-node').start({ + +// ${i18n.translate( + 'xpack.apm.tutorial.nodeClient.configure.commands.setRequiredServiceNameComment', + { + defaultMessage: 'Override the service name from package.json', + } +)} +// ${i18n.translate( + 'xpack.apm.tutorial.nodeClient.configure.commands.allowedCharactersComment', + { + defaultMessage: 'Allowed characters: a-z, A-Z, 0-9, -, _, and space', + } +)} +serviceName: '', + +// ${i18n.translate( + 'xpack.apm.tutorial.nodeClient.configure.commands.useIfApmRequiresTokenComment', + { + defaultMessage: 'Use if APM Server requires a secret token', + } +)} +secretToken: '{{secretToken}}', + +// ${i18n.translate( + 'xpack.apm.tutorial.nodeClient.configure.commands.setCustomApmServerUrlComment', + { + defaultMessage: + 'Set the custom APM Server URL (default: {defaultApmServerUrl})', + values: { defaultApmServerUrl: 'http://localhost:8200' }, + } +)} +serverUrl: '{{apmServerUrl}}', + +// ${i18n.translate( + 'xpack.apm.tutorial.nodeClient.configure.commands.setCustomServiceEnvironmentComment', + { + defaultMessage: 'Set the service environment', + } +)} +environment: 'production' +})`; diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/php.ts b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/php.ts new file mode 100644 index 00000000000000..443f3def8bb536 --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/php.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export const php = `elastic_apm.server_url="{{apmServerUrl}}" +elastic.apm.secret_token="{{secretToken}}" +elastic_apm.service_name="My service" +`; diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/rack.ts b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/rack.ts new file mode 100644 index 00000000000000..55043042e1e36c --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/rack.ts @@ -0,0 +1,50 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; + +export const rack = `# config/elastic_apm.yml: + +# ${i18n.translate( + 'xpack.apm.tutorial.rackClient.createConfig.commands.setServiceNameComment', + { + defaultMessage: + 'Set the service name - allowed characters: a-z, A-Z, 0-9, -, _ and space', + } +)} +# ${i18n.translate( + 'xpack.apm.tutorial.rackClient.createConfig.commands.defaultsToTheNameOfRackAppClassComment', + { + defaultMessage: "Defaults to the name of your Rack app's class.", + } +)} +service_name: 'my-service' + +# ${i18n.translate( + 'xpack.apm.tutorial.rackClient.createConfig.commands.useIfApmServerRequiresTokenComment', + { + defaultMessage: 'Use if APM Server requires a token', + } +)} +secret_token: '{{secretToken}}' + +# ${i18n.translate( + 'xpack.apm.tutorial.rackClient.createConfig.commands.setCustomApmServerComment', + { + defaultMessage: 'Set custom APM Server URL (default: {defaultServerUrl})', + values: { defaultServerUrl: 'http://localhost:8200' }, + } +)} +server_url: {{apmServerUrl}}, + +# ${i18n.translate( + 'xpack.apm.tutorial.rackClient.createConfig.commands.setServiceEnvironment', + { + defaultMessage: 'Set the service environment', + } +)} +environment: 'production'`; diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/rails.ts b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/rails.ts new file mode 100644 index 00000000000000..e0663709e10203 --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/rails.ts @@ -0,0 +1,22 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +// TODO: ${'http://localhost:8200'}' fallback server_url +export const rails = `# config/elastic_apm.yml: + +# Set the service name - allowed characters: a-z, A-Z, 0-9, -, _ and space +# Defaults to the name of your Rails app +service_name: 'my-service' + +# Use if APM Server requires a secret token +secret_token: '{{secretToken}}' + +# Set the custom APM Server URL (default: http://localhost:8200) +server_url: '{{apmServerUrl}}' + +# Set the service environment +environment: 'production'`; diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/rum.ts b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/rum.ts new file mode 100644 index 00000000000000..91a8283c8ae63e --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/rum.ts @@ -0,0 +1,60 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; + +// TODO: doesn't have token +export const rum = `import { init as initApm } from '@elastic/apm-rum' +var apm = initApm({ + + // ${i18n.translate( + 'xpack.apm.tutorial.jsClient.installDependency.commands.setRequiredServiceNameComment', + { + defaultMessage: + 'Set required service name (allowed characters: a-z, A-Z, 0-9, -, _, and space)', + } + )} + serviceName: 'your-app-name', + + // ${i18n.translate( + 'xpack.apm.tutorial.jsClient.installDependency.commands.setCustomApmServerUrlComment', + { + defaultMessage: + 'Set custom APM Server URL (default: {defaultApmServerUrl})', + values: { defaultApmServerUrl: 'http://localhost:8200' }, + } + )} + serverUrl: '{{apmServerUrl}}', + + // ${i18n.translate( + 'xpack.apm.tutorial.jsClient.installDependency.commands.setServiceVersionComment', + { + defaultMessage: + 'Set the service version (required for source map feature)', + } + )} + serviceVersion: '', + + // ${i18n.translate( + 'xpack.apm.tutorial.jsClient.installDependency.commands.setServiceEnvironmentComment', + { + defaultMessage: 'Set the service environment', + } + )} + environment: 'production' +})`; + +// TODO: doesn't have token/url +export const rumScript = `\ + + +`; diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/index.tsx b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/index.tsx new file mode 100644 index 00000000000000..b6e882a7a48ef0 --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/index.tsx @@ -0,0 +1,211 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { + EuiButton, + EuiButtonEmpty, + EuiCodeBlock, + EuiFlexGroup, + EuiFlexItem, + EuiLoadingSpinner, + EuiPopover, + EuiPopoverFooter, + EuiPopoverTitle, + EuiSelectable, + EuiSpacer, +} from '@elastic/eui'; +import { HttpStart } from 'kibana/public'; +import React, { useEffect, useState } from 'react'; +import styled from 'styled-components'; +import { APIReturnType } from '../../../../services/rest/createCallApmApi'; +import { CopyCommands } from '../copy_commands'; +import { getCommands } from './commands/get_commands'; + +interface Props { + variantId: string; + http: HttpStart; + basePath: string; + isCloudEnabled: boolean; +} + +const CentralizedContainer = styled.div` + display: flex; + justify-content: center; + align-items: center; +`; + +const onPremStandaloneOption = { + key: 'onPrem_standalone', + label: 'Default Standalone configuration', + apmServerUrl: 'http://localhost:8200', + secretKey: '', + checked: 'on', +}; + +type APIResponseType = APIReturnType<'GET /api/apm/fleet/agents'>; +const INITIAL_STATE: APIResponseType = { + agentsCredentials: [], + cloudAgentPolicyCredential: undefined, + cloudCredentials: undefined, +}; + +type SelectValuesType = 'onPrem_standalone' | 'cloud_standalone' | string; + +interface Credential { + key: string; + label: string; + apmServerUrl?: string; + secretToken?: string; + checked?: 'on'; +} + +function TutorialAgentSecretTokenSelector({ + variantId, + http, + basePath, + isCloudEnabled, +}: Props) { + const [isPopoverOpen, setIsPopoverOpen] = useState(false); + const [data, setData] = useState(INITIAL_STATE); + const [isLoading, setIsLoading] = useState(true); + const [options, setOptions] = useState([]); + const [option, setOption] = useState(); + + useEffect(() => { + const checkedOption = options.find(({ checked }) => checked === 'on'); + setOption(checkedOption); + }, [options]); + + useEffect(() => { + async function fetchData() { + setIsLoading(true); + try { + const response = await http.get('/api/apm/fleet/agents'); + setData(response as APIResponseType); + } catch (e) { + console.error('Error while fetching fleet agents.', e); + } + setIsLoading(false); + } + fetchData(); + }, [http]); + + useEffect(() => { + const newOptions = []; + if (isCloudEnabled) { + // has Elastic Cloud managed policy + if (data.cloudAgentPolicyCredential) { + const { + id, + name, + apmServerUrl, + secretToken, + } = data.cloudAgentPolicyCredential; + newOptions.push({ + key: id, + label: name, + apmServerUrl, + secretToken, + checked: 'on', + }); + } else { + // adds standalone cloud + newOptions.push({ + key: 'cloud_standalone', + label: 'Default Standalone configuration', + apmServerUrl: data.cloudCredentials?.apmServerUrl, + secretToken: data.cloudCredentials?.secretToken, + checked: 'on', + }); + } + } else { + // when onPrem + newOptions.push(onPremStandaloneOption); + } + + newOptions.push( + ...data.agentsCredentials?.map( + ({ id, name, apmServerUrl, secretToken }) => ({ + key: id, + label: name, + apmServerUrl, + secretToken, + }) + ) + ); + setOptions(newOptions); + }, [data, isCloudEnabled]); + + if (isLoading) { + return ( + + + + ); + } + + const command = getCommands({ + variantId, + environmentDetails: { + apmServerUrl: option?.apmServerUrl, + secretToken: option?.secretToken, + }, + }); + + function toggleIsPopoverOpen() { + setIsPopoverOpen((state) => !state); + } + + return ( + <> + + + + {option?.label} + + } + isOpen={isPopoverOpen} + closePopover={toggleIsPopoverOpen} + > + setOptions(newOptions)} + singleSelection + > + {(list, search) => ( +
+ {search} + {list} + + + Manage this list + + +
+ )} +
+
+
+ + + +
+ + {command} + + ); +} + +// eslint-disable-next-line import/no-default-export +export default TutorialAgentSecretTokenSelector; diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/rum_script.tsx b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/rum_script.tsx new file mode 100644 index 00000000000000..ac9ca53bdee6cf --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/rum_script.tsx @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React from 'react'; +import TutorialAgentSecretTokenSelector from './'; + +function TutorialConfigAgentRumScript() { + return ; +} + +// eslint-disable-next-line import/no-default-export +export default TutorialConfigAgentRumScript; diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/copy_commands.tsx b/x-pack/plugins/apm/public/components/shared/tutorial/copy_commands.tsx new file mode 100644 index 00000000000000..9e02efef059194 --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/tutorial/copy_commands.tsx @@ -0,0 +1,23 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { EuiButton, EuiCopy } from '@elastic/eui'; +import React from 'react'; + +interface Props { + commands: string; +} +export function CopyCommands({ commands }: Props) { + return ( + + {(copy) => ( + + Copy snippet + + )} + + ); +} diff --git a/x-pack/plugins/apm/public/plugin.ts b/x-pack/plugins/apm/public/plugin.ts index f8c8ffb8550808..868be2d5281c26 100644 --- a/x-pack/plugins/apm/public/plugin.ts +++ b/x-pack/plugins/apm/public/plugin.ts @@ -175,6 +175,16 @@ export class ApmPlugin implements Plugin { () => import('./components/shared/tutorial_fleet_instructions') ); + pluginSetupDeps.home?.tutorials.registerCustomComponent( + 'TutorialConfigAgent', + () => import('./components/shared/tutorial/config_agent') + ); + + pluginSetupDeps.home?.tutorials.registerCustomComponent( + 'TutorialConfigAgentRumScript', + () => import('./components/shared/tutorial/config_agent/rum_script') + ); + plugins.observability.dashboard.register({ appName: 'apm', hasData: async () => { diff --git a/x-pack/plugins/apm/server/lib/fleet/get_agents.ts b/x-pack/plugins/apm/server/lib/fleet/get_agents.ts new file mode 100644 index 00000000000000..5ee44bb3ad1746 --- /dev/null +++ b/x-pack/plugins/apm/server/lib/fleet/get_agents.ts @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + CoreSetup, + CoreStart, + SavedObjectsClientContract, +} from 'kibana/server'; +import { APMPluginStartDependencies } from '../../types'; +import { getInternalSavedObjectsClient } from '../helpers/get_internal_saved_objects_client'; + +export async function getFleetAgents({ + policyIds, + core, + fleetPluginStart, +}: { + policyIds: string[]; + core: { setup: CoreSetup; start: () => Promise }; + fleetPluginStart: NonNullable; +}) { + // @ts-ignore + const savedObjectsClient: SavedObjectsClientContract = await getInternalSavedObjectsClient( + core.setup + ); + + return await fleetPluginStart.agentPolicyService.getByIds( + savedObjectsClient, + policyIds + ); +} diff --git a/x-pack/plugins/apm/server/routes/fleet.ts b/x-pack/plugins/apm/server/routes/fleet.ts index e2a394414308a8..3e2d63a5e70e41 100644 --- a/x-pack/plugins/apm/server/routes/fleet.ts +++ b/x-pack/plugins/apm/server/routes/fleet.ts @@ -5,10 +5,15 @@ * 2.0. */ +import { keyBy } from 'lodash'; +import { AgentPolicy, PackagePolicy } from '../../../fleet/common'; +import { getFleetAgents } from '../lib/fleet/get_agents'; import { getApmPackgePolicies } from '../lib/fleet/get_apm_package_policies'; import { createApmServerRoute } from './create_apm_server_route'; import { createApmServerRouteRepository } from './create_apm_server_route_repository'; +const POLICY_ELASTIC_AGENT_ON_CLOUD = 'policy-elastic-agent-on-cloud'; + const hasFleetDataRoute = createApmServerRoute({ endpoint: 'GET /api/apm/fleet/has_data', options: { tags: [] }, @@ -22,6 +27,65 @@ const hasFleetDataRoute = createApmServerRoute({ }, }); -export const ApmFleetRouteRepository = createApmServerRouteRepository().add( - hasFleetDataRoute -); +function getAgentPolicyCredentials( + agent: AgentPolicy, + policiesGroupedById: Record +) { + const packagePolicy = policiesGroupedById[agent.id]; + const apmServerCompiledInputs = + packagePolicy.inputs[0].compiled_input['apm-server']; + return { + id: agent.id, + name: agent.name, + apmServerUrl: apmServerCompiledInputs?.host, + secretToken: apmServerCompiledInputs?.secret_token, + }; +} + +const fleetAgentsRoute = createApmServerRoute({ + endpoint: 'GET /api/apm/fleet/agents', + options: { tags: [] }, + handler: async ({ core, plugins }) => { + const cloudSetup = plugins.cloud?.setup; + const cloudCredentials = cloudSetup + ? { + apmServerUrl: cloudSetup?.apm.url, + secretToken: cloudSetup?.apm.secretToken, + } + : undefined; + + const fleetPluginStart = await plugins.fleet.start(); + // fetches package policies that contains APM integrations + const packagePolicies = await getApmPackgePolicies({ + core, + fleetPluginStart, + }); + + const policiesGroupedById = keyBy(packagePolicies.items, 'policy_id'); + + // fetches all agents with the found package policies + const agents = await getFleetAgents({ + policyIds: Object.keys(policiesGroupedById), + core, + fleetPluginStart, + }); + + const cloudAgentPolicy = agents.find( + ({ name }) => name === POLICY_ELASTIC_AGENT_ON_CLOUD + ); + + return { + cloudAgentPolicyCredential: cloudAgentPolicy + ? getAgentPolicyCredentials(cloudAgentPolicy, policiesGroupedById) + : undefined, + cloudCredentials, + agentsCredentials: agents.map((agent) => { + return getAgentPolicyCredentials(agent, policiesGroupedById); + }), + }; + }, +}); + +export const ApmFleetRouteRepository = createApmServerRouteRepository() + .add(hasFleetDataRoute) + .add(fleetAgentsRoute); diff --git a/x-pack/plugins/apm/server/tutorial/instructions/apm_agent_instructions.ts b/x-pack/plugins/apm/server/tutorial/instructions/apm_agent_instructions.ts index ba11a996f00df4..e2bf09dae5bede 100644 --- a/x-pack/plugins/apm/server/tutorial/instructions/apm_agent_instructions.ts +++ b/x-pack/plugins/apm/server/tutorial/instructions/apm_agent_instructions.ts @@ -31,55 +31,7 @@ export const createNodeAgentInstructions = ( APM services are created programmatically based on the `serviceName`. \ This agent supports a variety of frameworks but can also be used with your custom stack.', }), - commands: `// ${i18n.translate( - 'xpack.apm.tutorial.nodeClient.configure.commands.addThisToTheFileTopComment', - { - defaultMessage: - 'Add this to the VERY top of the first file loaded in your app', - } - )} -var apm = require('elastic-apm-node').start({curlyOpen} - - // ${i18n.translate( - 'xpack.apm.tutorial.nodeClient.configure.commands.setRequiredServiceNameComment', - { - defaultMessage: 'Override the service name from package.json', - } - )} - // ${i18n.translate( - 'xpack.apm.tutorial.nodeClient.configure.commands.allowedCharactersComment', - { - defaultMessage: 'Allowed characters: a-z, A-Z, 0-9, -, _, and space', - } - )} - serviceName: '', - - // ${i18n.translate( - 'xpack.apm.tutorial.nodeClient.configure.commands.useIfApmRequiresTokenComment', - { - defaultMessage: 'Use if APM Server requires a secret token', - } - )} - secretToken: '${secretToken}', - - // ${i18n.translate( - 'xpack.apm.tutorial.nodeClient.configure.commands.setCustomApmServerUrlComment', - { - defaultMessage: - 'Set the custom APM Server URL (default: {defaultApmServerUrl})', - values: { defaultApmServerUrl: 'http://localhost:8200' }, - } - )} - serverUrl: '${apmServerUrl}', - - // ${i18n.translate( - 'xpack.apm.tutorial.nodeClient.configure.commands.setCustomServiceEnvironmentComment', - { - defaultMessage: 'Set the service environment', - } - )} - environment: 'production' -{curlyClose})`.split('\n'), + customComponentName: 'TutorialConfigAgent', textPost: i18n.translate( 'xpack.apm.tutorial.nodeClient.configure.textPost', { @@ -122,70 +74,7 @@ export const createDjangoAgentInstructions = ( APM services are created programmatically based on the `SERVICE_NAME`.', } ), - commands: `# ${i18n.translate( - 'xpack.apm.tutorial.djangoClient.configure.commands.addAgentComment', - { - defaultMessage: 'Add the agent to the installed apps', - } - )} -INSTALLED_APPS = ( - 'elasticapm.contrib.django', - # ... -) - -ELASTIC_APM = {curlyOpen} - # ${i18n.translate( - 'xpack.apm.tutorial.djangoClient.configure.commands.setRequiredServiceNameComment', - { - defaultMessage: 'Set the required service name. Allowed characters:', - } - )} - # ${i18n.translate( - 'xpack.apm.tutorial.djangoClient.configure.commands.allowedCharactersComment', - { - defaultMessage: 'a-z, A-Z, 0-9, -, _, and space', - } - )} - 'SERVICE_NAME': '', - - # ${i18n.translate( - 'xpack.apm.tutorial.djangoClient.configure.commands.useIfApmServerRequiresTokenComment', - { - defaultMessage: 'Use if APM Server requires a secret token', - } - )} - 'SECRET_TOKEN': '${secretToken}', - - # ${i18n.translate( - 'xpack.apm.tutorial.djangoClient.configure.commands.setCustomApmServerUrlComment', - { - defaultMessage: - 'Set the custom APM Server URL (default: {defaultApmServerUrl})', - values: { defaultApmServerUrl: 'http://localhost:8200' }, - } - )} - 'SERVER_URL': '${apmServerUrl}', - - # ${i18n.translate( - 'xpack.apm.tutorial.djangoClient.configure.commands.setServiceEnvironmentComment', - { - defaultMessage: 'Set the service environment', - } - )} - 'ENVIRONMENT': 'production', -{curlyClose} - -# ${i18n.translate( - 'xpack.apm.tutorial.djangoClient.configure.commands.addTracingMiddlewareComment', - { - defaultMessage: - 'To send performance metrics, add our tracing middleware:', - } - )} -MIDDLEWARE = ( - 'elasticapm.contrib.django.middleware.TracingMiddleware', - #... -)`.split('\n'), + customComponentName: 'TutorialConfigAgent', textPost: i18n.translate( 'xpack.apm.tutorial.djangoClient.configure.textPost', { @@ -225,67 +114,7 @@ export const createFlaskAgentInstructions = ( APM services are created programmatically based on the `SERVICE_NAME`.', } ), - commands: `# ${i18n.translate( - 'xpack.apm.tutorial.flaskClient.configure.commands.initializeUsingEnvironmentVariablesComment', - { - defaultMessage: 'initialize using environment variables', - } - )} -from elasticapm.contrib.flask import ElasticAPM -app = Flask(__name__) -apm = ElasticAPM(app) - -# ${i18n.translate( - 'xpack.apm.tutorial.flaskClient.configure.commands.configureElasticApmComment', - { - defaultMessage: - "or configure to use ELASTIC_APM in your application's settings", - } - )} -from elasticapm.contrib.flask import ElasticAPM -app.config['ELASTIC_APM'] = {curlyOpen} - # ${i18n.translate( - 'xpack.apm.tutorial.flaskClient.configure.commands.setRequiredServiceNameComment', - { - defaultMessage: 'Set the required service name. Allowed characters:', - } - )} - # ${i18n.translate( - 'xpack.apm.tutorial.flaskClient.configure.commands.allowedCharactersComment', - { - defaultMessage: 'a-z, A-Z, 0-9, -, _, and space', - } - )} - 'SERVICE_NAME': '', - - # ${i18n.translate( - 'xpack.apm.tutorial.flaskClient.configure.commands.useIfApmServerRequiresTokenComment', - { - defaultMessage: 'Use if APM Server requires a secret token', - } - )} - 'SECRET_TOKEN': '${secretToken}', - - # ${i18n.translate( - 'xpack.apm.tutorial.flaskClient.configure.commands.setCustomApmServerUrlComment', - { - defaultMessage: - 'Set the custom APM Server URL (default: {defaultApmServerUrl})', - values: { defaultApmServerUrl: 'http://localhost:8200' }, - } - )} - 'SERVER_URL': '${apmServerUrl}', - - # ${i18n.translate( - 'xpack.apm.tutorial.flaskClient.configure.commands.setServiceEnvironmentComment', - { - defaultMessage: 'Set the service environment', - } - )} - 'ENVIRONMENT': 'production', -{curlyClose} - -apm = ElasticAPM(app)`.split('\n'), + customComponentName: 'TutorialConfigAgent', textPost: i18n.translate( 'xpack.apm.tutorial.flaskClient.configure.textPost', { @@ -325,20 +154,7 @@ export const createRailsAgentInstructions = ( values: { configFile: '`config/elastic_apm.yml`' }, } ), - commands: `# config/elastic_apm.yml: - -# Set the service name - allowed characters: a-z, A-Z, 0-9, -, _ and space -# Defaults to the name of your Rails app -service_name: 'my-service' - -# Use if APM Server requires a secret token -secret_token: '${secretToken}' - -# Set the custom APM Server URL (default: http://localhost:8200) -server_url: '${apmServerUrl || 'http://localhost:8200'}' - -# Set the service environment -environment: 'production'`.split('\n'), + customComponentName: 'TutorialConfigAgent', textPost: i18n.translate( 'xpack.apm.tutorial.railsClient.configure.textPost', { @@ -413,48 +229,7 @@ export const createRackAgentInstructions = ( values: { configFile: '`config/elastic_apm.yml`' }, } ), - commands: `# config/elastic_apm.yml: - -# ${i18n.translate( - 'xpack.apm.tutorial.rackClient.createConfig.commands.setServiceNameComment', - { - defaultMessage: - 'Set the service name - allowed characters: a-z, A-Z, 0-9, -, _ and space', - } - )} -# ${i18n.translate( - 'xpack.apm.tutorial.rackClient.createConfig.commands.defaultsToTheNameOfRackAppClassComment', - { - defaultMessage: "Defaults to the name of your Rack app's class.", - } - )} -service_name: 'my-service' - -# ${i18n.translate( - 'xpack.apm.tutorial.rackClient.createConfig.commands.useIfApmServerRequiresTokenComment', - { - defaultMessage: 'Use if APM Server requires a token', - } - )} -secret_token: '${secretToken}' - -# ${i18n.translate( - 'xpack.apm.tutorial.rackClient.createConfig.commands.setCustomApmServerComment', - { - defaultMessage: - 'Set custom APM Server URL (default: {defaultServerUrl})', - values: { defaultServerUrl: 'http://localhost:8200' }, - } - )} -server_url: '${apmServerUrl || 'http://localhost:8200'}', - -# ${i18n.translate( - 'xpack.apm.tutorial.rackClient.createConfig.commands.setServiceEnvironment', - { - defaultMessage: 'Set the service environment', - } - )} -environment: 'production'`.split('\n'), + customComponentName: 'TutorialConfigAgent', textPost: i18n.translate( 'xpack.apm.tutorial.rackClient.createConfig.textPost', { @@ -506,45 +281,7 @@ for details on how to enable RUM support.', The Agent can then be initialized and configured in your application like this:', } ), - commands: `import {curlyOpen} init as initApm {curlyClose} from '@elastic/apm-rum' -var apm = initApm({curlyOpen} - - // ${i18n.translate( - 'xpack.apm.tutorial.jsClient.installDependency.commands.setRequiredServiceNameComment', - { - defaultMessage: - 'Set required service name (allowed characters: a-z, A-Z, 0-9, -, _, and space)', - } - )} - serviceName: 'your-app-name', - - // ${i18n.translate( - 'xpack.apm.tutorial.jsClient.installDependency.commands.setCustomApmServerUrlComment', - { - defaultMessage: - 'Set custom APM Server URL (default: {defaultApmServerUrl})', - values: { defaultApmServerUrl: 'http://localhost:8200' }, - } - )} - serverUrl: '${apmServerUrl}', - - // ${i18n.translate( - 'xpack.apm.tutorial.jsClient.installDependency.commands.setServiceVersionComment', - { - defaultMessage: - 'Set the service version (required for source map feature)', - } - )} - serviceVersion: '', - - // ${i18n.translate( - 'xpack.apm.tutorial.jsClient.installDependency.commands.setServiceEnvironmentComment', - { - defaultMessage: 'Set the service environment', - } - )} - environment: 'production' -{curlyClose})`.split('\n'), + customComponentName: 'TutorialConfigAgent', textPost: i18n.translate( 'xpack.apm.tutorial.jsClient.installDependency.textPost', { @@ -575,15 +312,7 @@ and host the file on your Server/CDN before deploying to production.", 'https://unpkg.com/@elastic/apm-rum/dist/bundles/elastic-apm-rum.umd.min.js', }, }), - commands: `\ - - -`.split('\n'), + customComponentName: 'TutorialConfigAgentRumScript', }, ]; @@ -610,55 +339,7 @@ export const createGoAgentInstructions = ( APM services are created programmatically based on the executable \ file name, or the `ELASTIC_APM_SERVICE_NAME` environment variable.', }), - commands: `# ${i18n.translate( - 'xpack.apm.tutorial.goClient.configure.commands.initializeUsingEnvironmentVariablesComment', - { - defaultMessage: 'Initialize using environment variables:', - } - )} - -# ${i18n.translate( - 'xpack.apm.tutorial.goClient.configure.commands.setServiceNameComment', - { - defaultMessage: - 'Set the service name. Allowed characters: # a-z, A-Z, 0-9, -, _, and space.', - } - )} -# ${i18n.translate( - 'xpack.apm.tutorial.goClient.configure.commands.usedExecutableNameComment', - { - defaultMessage: - 'If ELASTIC_APM_SERVICE_NAME is not specified, the executable name will be used.', - } - )} -export ELASTIC_APM_SERVICE_NAME= - -# ${i18n.translate( - 'xpack.apm.tutorial.goClient.configure.commands.setCustomApmServerUrlComment', - { - defaultMessage: - 'Set custom APM Server URL (default: {defaultApmServerUrl})', - values: { defaultApmServerUrl: 'http://localhost:8200' }, - } - )} -export ELASTIC_APM_SERVER_URL=${apmServerUrl} - -# ${i18n.translate( - 'xpack.apm.tutorial.goClient.configure.commands.useIfApmRequiresTokenComment', - { - defaultMessage: 'Use if APM Server requires a secret token', - } - )} -export ELASTIC_APM_SECRET_TOKEN=${secretToken} - -# ${i18n.translate( - 'xpack.apm.tutorial.goClient.configure.commands.setServiceEnvironment', - { - defaultMessage: 'Set the service environment', - } - )} -export ELASTIC_APM_ENVIRONMENT= -`.split('\n'), + customComponentName: 'TutorialConfigAgent', textPost: i18n.translate('xpack.apm.tutorial.goClient.configure.textPost', { defaultMessage: 'See the [documentation]({documentationLink}) for advanced configuration.', @@ -743,13 +424,7 @@ Do **not** add the agent as a dependency to your application.', values: { customApmServerUrl: 'http://localhost:8200' }, } ), - commands: `java -javaagent:/path/to/elastic-apm-agent-.jar \\ - -Delastic.apm.service_name=my-application \\ - -Delastic.apm.server_urls=${apmServerUrl || 'http://localhost:8200'} \\ - -Delastic.apm.secret_token=${secretToken} \\ - -Delastic.apm.environment=production \\ - -Delastic.apm.application_packages=org.example \\ - -jar my-application.jar`.split('\n'), + customComponentName: 'TutorialConfigAgent', textPost: i18n.translate( 'xpack.apm.tutorial.javaClient.startApplication.textPost', { @@ -837,16 +512,7 @@ export const createDotNetAgentInstructions = ( defaultMessage: 'Sample appsettings.json file:', } ), - commands: `{curlyOpen} - "ElasticApm": {curlyOpen} - "SecretToken": "${secretToken}", - "ServerUrls": "${ - apmServerUrl || 'http://localhost:8200' - }", //Set custom APM Server URL (default: http://localhost:8200) - "ServiceName": "MyApp", //allowed characters: a-z, A-Z, 0-9, -, _, and space. Default is the entry assembly of the application - "Environment": "production", // Set the service environment - {curlyClose} -{curlyClose}`.split('\n'), + customComponentName: 'TutorialConfigAgent', textPost: i18n.translate( 'xpack.apm.tutorial.dotNetClient.configureAgent.textPost', { @@ -913,12 +579,7 @@ export const createPhpAgentInstructions = ( 'APM is automatically started when your app boots. Configure the agent either via `php.ini` file:', } ), - commands: `elastic_apm.server_url="${ - apmServerUrl || 'http://localhost:8200' - }" -elastic.apm.secret_token="${secretToken}" -elastic_apm.service_name="My service" -`.split('\n'), + customComponentName: 'TutorialConfigAgent', textPost: i18n.translate( 'xpack.apm.tutorial.phpClient.configure.textPost', { diff --git a/x-pack/plugins/fleet/server/plugin.ts b/x-pack/plugins/fleet/server/plugin.ts index f933965effebfb..1f8f54261c7210 100644 --- a/x-pack/plugins/fleet/server/plugin.ts +++ b/x-pack/plugins/fleet/server/plugin.ts @@ -328,6 +328,7 @@ export class FleetPlugin list: agentPolicyService.list, getDefaultAgentPolicyId: agentPolicyService.getDefaultAgentPolicyId, getFullAgentPolicy: agentPolicyService.getFullAgentPolicy, + getByIds: agentPolicyService.getByIDs, }, packagePolicyService, registerExternalCallback: (type: ExternalCallback[0], callback: ExternalCallback[1]) => { diff --git a/x-pack/plugins/fleet/server/services/index.ts b/x-pack/plugins/fleet/server/services/index.ts index ebddb695d695b2..f82415987e5ac6 100644 --- a/x-pack/plugins/fleet/server/services/index.ts +++ b/x-pack/plugins/fleet/server/services/index.ts @@ -69,6 +69,7 @@ export interface AgentPolicyServiceInterface { list: typeof agentPolicyService['list']; getDefaultAgentPolicyId: typeof agentPolicyService['getDefaultAgentPolicyId']; getFullAgentPolicy: typeof agentPolicyService['getFullAgentPolicy']; + getByIds: typeof agentPolicyService['getByIDs']; } // Saved object services From 798503ab84972791d5667a8b24ea56d0270bba7f Mon Sep 17 00:00:00 2001 From: cauemarcondes Date: Fri, 18 Jun 2021 15:35:24 -0400 Subject: [PATCH 02/11] refactoring --- .../tutorial/config_agent/commands/django.ts | 4 +- .../tutorial/config_agent/commands/dotnet.ts | 4 +- .../tutorial/config_agent/commands/flask.ts | 4 +- .../tutorial/config_agent/commands/go.ts | 4 +- .../tutorial/config_agent/commands/java.ts | 4 +- .../tutorial/config_agent/commands/node.ts | 4 +- .../tutorial/config_agent/commands/php.ts | 4 +- .../tutorial/config_agent/commands/rack.ts | 4 +- .../tutorial/config_agent/commands/rails.ts | 4 +- .../tutorial/config_agent/commands/rum.ts | 2 +- .../environment_configuration_selector.tsx | 132 ++++++++ .../tutorial/config_agent/index.test.tsx | 298 ++++++++++++++++++ .../shared/tutorial/config_agent/index.tsx | 222 ++++++------- .../shared/tutorial/copy_commands.tsx | 5 +- x-pack/plugins/apm/server/routes/fleet.ts | 38 +-- 15 files changed, 570 insertions(+), 163 deletions(-) create mode 100644 x-pack/plugins/apm/public/components/shared/tutorial/config_agent/environment_configuration_selector.tsx create mode 100644 x-pack/plugins/apm/public/components/shared/tutorial/config_agent/index.test.tsx diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/django.ts b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/django.ts index 686fcd02765492..97b5f3315bcdbf 100644 --- a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/django.ts +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/django.ts @@ -39,7 +39,7 @@ ELASTIC_APM = {curlyOpen} defaultMessage: 'Use if APM Server requires a secret token', } )} -'SECRET_TOKEN': '{{secretToken}}', +'SECRET_TOKEN': '{{{secretToken}}}', # ${i18n.translate( 'xpack.apm.tutorial.djangoClient.configure.commands.setCustomApmServerUrlComment', @@ -49,7 +49,7 @@ ELASTIC_APM = {curlyOpen} values: { defaultApmServerUrl: 'http://localhost:8200' }, } )} -'SERVER_URL': '{{apmServerUrl}}', +'SERVER_URL': '{{{apmServerUrl}}}', # ${i18n.translate( 'xpack.apm.tutorial.djangoClient.configure.commands.setServiceEnvironmentComment', diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/dotnet.ts b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/dotnet.ts index d11234e0b546c6..0ed7a874a95aea 100644 --- a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/dotnet.ts +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/dotnet.ts @@ -8,8 +8,8 @@ export const dotnet = `{ "ElasticApm": { -"SecretToken": "{{secretToken}}", -"ServerUrls": "{{apmServerUrl}}", //Set custom APM Server URL (default: http://localhost:8200) +"SecretToken": "{{{secretToken}}}", +"ServerUrls": "{{{apmServerUrl}}}", //Set custom APM Server URL (default: http://localhost:8200) "ServiceName": "MyApp", //allowed characters: a-z, A-Z, 0-9, -, _, and space. Default is the entry assembly of the application "Environment": "production", // Set the service environment } diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/flask.ts b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/flask.ts index d97b5e71723280..e4d7fd188e7c6f 100644 --- a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/flask.ts +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/flask.ts @@ -46,7 +46,7 @@ app.config['ELASTIC_APM'] = {curlyOpen} defaultMessage: 'Use if APM Server requires a secret token', } )} -'SECRET_TOKEN': '{{secretToken}}', +'SECRET_TOKEN': '{{{secretToken}}}', # ${i18n.translate( 'xpack.apm.tutorial.flaskClient.configure.commands.setCustomApmServerUrlComment', @@ -56,7 +56,7 @@ app.config['ELASTIC_APM'] = {curlyOpen} values: { defaultApmServerUrl: 'http://localhost:8200' }, } )} -'SERVER_URL': '{{apmServerUrl}}', +'SERVER_URL': '{{{apmServerUrl}}}', # ${i18n.translate( 'xpack.apm.tutorial.flaskClient.configure.commands.setServiceEnvironmentComment', diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/go.ts b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/go.ts index a1878dc382764f..a3900420d6fdec 100644 --- a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/go.ts +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/go.ts @@ -38,7 +38,7 @@ export ELASTIC_APM_SERVICE_NAME= values: { defaultApmServerUrl: 'http://localhost:8200' }, } )} -export ELASTIC_APM_SERVER_URL={{apmServerUrl}} +export ELASTIC_APM_SERVER_URL={{{apmServerUrl}}} # ${i18n.translate( 'xpack.apm.tutorial.goClient.configure.commands.useIfApmRequiresTokenComment', @@ -46,7 +46,7 @@ export ELASTIC_APM_SERVER_URL={{apmServerUrl}} defaultMessage: 'Use if APM Server requires a secret token', } )} -export ELASTIC_APM_SECRET_TOKEN={{secretToken}} +export ELASTIC_APM_SECRET_TOKEN={{{secretToken}}} # ${i18n.translate( 'xpack.apm.tutorial.goClient.configure.commands.setServiceEnvironment', diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/java.ts b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/java.ts index 2d8c38d73966c1..28590f889b4a4b 100644 --- a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/java.ts +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/java.ts @@ -7,8 +7,8 @@ export const java = `java -javaagent:/path/to/elastic-apm-agent-.jar \\ -Delastic.apm.service_name=my-application \\ --Delastic.apm.server_urls= {{apmServerUrl}} \\ --Delastic.apm.secret_token= {{secretToken}} \\ +-Delastic.apm.server_urls= {{{apmServerUrl}}} \\ +-Delastic.apm.secret_token= {{{{secretToken}}}} \\ -Delastic.apm.environment=production \\ -Delastic.apm.application_packages=org.example \\ -jar my-application.jar`; diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/node.ts b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/node.ts index 553d861cfb0c30..31f9fac0ed480d 100644 --- a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/node.ts +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/node.ts @@ -35,7 +35,7 @@ serviceName: '', defaultMessage: 'Use if APM Server requires a secret token', } )} -secretToken: '{{secretToken}}', +secretToken: '{{{secretToken}}}', // ${i18n.translate( 'xpack.apm.tutorial.nodeClient.configure.commands.setCustomApmServerUrlComment', @@ -45,7 +45,7 @@ secretToken: '{{secretToken}}', values: { defaultApmServerUrl: 'http://localhost:8200' }, } )} -serverUrl: '{{apmServerUrl}}', +serverUrl: '{{{apmServerUrl}}}', // ${i18n.translate( 'xpack.apm.tutorial.nodeClient.configure.commands.setCustomServiceEnvironmentComment', diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/php.ts b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/php.ts index 443f3def8bb536..ea7e8764f89ad1 100644 --- a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/php.ts +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/php.ts @@ -5,7 +5,7 @@ * 2.0. */ -export const php = `elastic_apm.server_url="{{apmServerUrl}}" -elastic.apm.secret_token="{{secretToken}}" +export const php = `elastic_apm.server_url="{{{apmServerUrl}}}" +elastic.apm.secret_token="{{{secretToken}}}" elastic_apm.service_name="My service" `; diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/rack.ts b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/rack.ts index 55043042e1e36c..7adf99366f615d 100644 --- a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/rack.ts +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/rack.ts @@ -30,7 +30,7 @@ service_name: 'my-service' defaultMessage: 'Use if APM Server requires a token', } )} -secret_token: '{{secretToken}}' +secret_token: '{{{secretToken}}}' # ${i18n.translate( 'xpack.apm.tutorial.rackClient.createConfig.commands.setCustomApmServerComment', @@ -39,7 +39,7 @@ secret_token: '{{secretToken}}' values: { defaultServerUrl: 'http://localhost:8200' }, } )} -server_url: {{apmServerUrl}}, +server_url: {{{apmServerUrl}}}, # ${i18n.translate( 'xpack.apm.tutorial.rackClient.createConfig.commands.setServiceEnvironment', diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/rails.ts b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/rails.ts index e0663709e10203..faf816c6b5bb71 100644 --- a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/rails.ts +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/rails.ts @@ -13,10 +13,10 @@ export const rails = `# config/elastic_apm.yml: service_name: 'my-service' # Use if APM Server requires a secret token -secret_token: '{{secretToken}}' +secret_token: '{{{secretToken}}}' # Set the custom APM Server URL (default: http://localhost:8200) -server_url: '{{apmServerUrl}}' +server_url: '{{{apmServerUrl}}}' # Set the service environment environment: 'production'`; diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/rum.ts b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/rum.ts index 91a8283c8ae63e..96e5ed6b082655 100644 --- a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/rum.ts +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/rum.ts @@ -28,7 +28,7 @@ var apm = initApm({ values: { defaultApmServerUrl: 'http://localhost:8200' }, } )} - serverUrl: '{{apmServerUrl}}', + serverUrl: '{{{apmServerUrl}}}', // ${i18n.translate( 'xpack.apm.tutorial.jsClient.installDependency.commands.setServiceVersionComment', diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/environment_configuration_selector.tsx b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/environment_configuration_selector.tsx new file mode 100644 index 00000000000000..e22eec6b1ed3ef --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/environment_configuration_selector.tsx @@ -0,0 +1,132 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + EuiButtonEmpty, + EuiFlexGroup, + EuiFlexItem, + EuiPopover, + EuiPopoverFooter, + EuiPopoverTitle, + EuiSelectable, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import React, { useEffect, useState } from 'react'; +import styled from 'styled-components'; +import { px } from '../../../../style/variables'; + +export interface EnvironmentConfigurationOption { + key: string; + label: string; + apmServerUrl?: string; + secretToken?: string; + checked?: 'on'; +} + +const StyledEuiButtomEmpty = styled(EuiButtonEmpty)` + .euiButtonContent { + display: flex; + justify-content: space-between; + } +`; + +interface Props { + options: EnvironmentConfigurationOption[]; + selectedOption?: EnvironmentConfigurationOption; + onChange: (selectedOption?: EnvironmentConfigurationOption) => void; + fleetLink: { + label: string; + href: string; + }; +} + +function findCheckedOption(options: EnvironmentConfigurationOption[]) { + return options.find(({ checked }) => checked === 'on'); +} + +export function EnvironmentConfigurationSelector({ + options, + selectedOption, + onChange, + fleetLink, +}: Props) { + const [isPopoverOpen, setIsPopoverOpen] = useState(false); + const [availableOptions, setAvailableOptions] = useState< + EnvironmentConfigurationOption[] + >(options); + + useEffect(() => { + const checkedOption = findCheckedOption(availableOptions); + onChange(checkedOption); + }, [availableOptions, onChange]); + + function toggleIsPopoverOpen() { + setIsPopoverOpen((state) => !state); + } + + return ( + + {selectedOption?.label} + + } + isOpen={isPopoverOpen} + closePopover={toggleIsPopoverOpen} + > +
+ { + const nextSelectedOption = findCheckedOption(newOptions); + // When there is no checked option don't update the options so we always have at least one option selected + if (nextSelectedOption) { + setAvailableOptions(newOptions); + } + }} + singleSelection + > + {(list, search) => { + return ( + <> + {search} + {list} + + + + + {fleetLink.label} + + + + + + ); + }} + +
+
+ ); +} diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/index.test.tsx b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/index.test.tsx new file mode 100644 index 00000000000000..270a97b79ec1cd --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/index.test.tsx @@ -0,0 +1,298 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { getEnvironmentConfigurationOptions } from './'; +import { APIReturnType } from '../../../../services/rest/createCallApmApi'; + +type APIResponseType = APIReturnType<'GET /api/apm/fleet/agents'>; + +const policyElasticAgentOnCloud = { + id: '3', + name: 'policy-elastic-agent-on-cloud', + apmServerUrl: 'baz', + secretToken: 'baz', +}; + +const agents = [ + { + id: '1', + name: 'agent foo', + apmServerUrl: 'foo', + secretToken: 'foo', + }, + { + id: '2', + name: 'agent bar', + apmServerUrl: 'bar', + secretToken: 'bar', + }, +]; + +describe('Tutorial config agent', () => { + describe('getEnvironmentConfigurationOptions', () => { + describe('running on cloud', () => { + describe('with APM on cloud', () => { + it('shows apm on cloud standalone option', () => { + const data: APIResponseType = { + agents: [], + cloudStandaloneSetup: { + apmServerUrl: 'foo', + secretToken: 'bar', + }, + hasPolicyElasticOnCloud: false, + }; + const options = getEnvironmentConfigurationOptions({ + isCloudEnabled: true, + data, + }); + expect(options).toEqual([ + { + key: 'cloud_standalone', + label: 'Default Standalone configuration', + apmServerUrl: 'foo', + secretToken: 'bar', + checked: 'on', + }, + ]); + }); + it('shows apm on cloud standalone option and fleet agents options', () => { + const data: APIResponseType = { + agents, + cloudStandaloneSetup: { + apmServerUrl: 'foo', + secretToken: 'bar', + }, + hasPolicyElasticOnCloud: false, + }; + const options = getEnvironmentConfigurationOptions({ + isCloudEnabled: true, + data, + }); + expect(options).toEqual([ + { + key: 'cloud_standalone', + label: 'Default Standalone configuration', + apmServerUrl: 'foo', + secretToken: 'bar', + checked: 'on', + }, + { + key: '1', + label: 'agent foo', + apmServerUrl: 'foo', + secretToken: 'foo', + checked: undefined, + }, + { + key: '2', + label: 'agent bar', + apmServerUrl: 'bar', + secretToken: 'bar', + checked: undefined, + }, + ]); + }); + it('selects policy elastic agent on cloud when available', () => { + const data: APIResponseType = { + agents: [policyElasticAgentOnCloud, ...agents], + cloudStandaloneSetup: { + apmServerUrl: 'foo', + secretToken: 'bar', + }, + hasPolicyElasticOnCloud: true, + }; + const options = getEnvironmentConfigurationOptions({ + isCloudEnabled: true, + data, + }); + expect(options).toEqual([ + { + key: 'cloud_standalone', + label: 'Default Standalone configuration', + apmServerUrl: 'foo', + secretToken: 'bar', + checked: undefined, + }, + { + key: '3', + label: 'policy-elastic-agent-on-cloud', + apmServerUrl: 'baz', + secretToken: 'baz', + checked: 'on', + }, + { + key: '1', + label: 'agent foo', + apmServerUrl: 'foo', + secretToken: 'foo', + checked: undefined, + }, + { + key: '2', + label: 'agent bar', + apmServerUrl: 'bar', + secretToken: 'bar', + checked: undefined, + }, + ]); + }); + }); + describe('with APM on prem', () => { + it('shows apm on prem standalone option', () => { + const data: APIResponseType = { + agents: [], + cloudStandaloneSetup: undefined, + hasPolicyElasticOnCloud: false, + }; + const options = getEnvironmentConfigurationOptions({ + isCloudEnabled: true, + data, + }); + expect(options).toEqual([ + { + key: 'onPrem_standalone', + label: 'Default Standalone configuration', + apmServerUrl: 'http://localhost:8200', + secretToken: '', + checked: 'on', + }, + ]); + }); + it('shows apm on prem standalone option and fleet agents options', () => { + const data: APIResponseType = { + agents, + cloudStandaloneSetup: undefined, + hasPolicyElasticOnCloud: false, + }; + const options = getEnvironmentConfigurationOptions({ + isCloudEnabled: true, + data, + }); + expect(options).toEqual([ + { + key: 'onPrem_standalone', + label: 'Default Standalone configuration', + apmServerUrl: 'http://localhost:8200', + secretToken: '', + checked: 'on', + }, + { + key: '1', + label: 'agent foo', + apmServerUrl: 'foo', + secretToken: 'foo', + checked: undefined, + }, + { + key: '2', + label: 'agent bar', + apmServerUrl: 'bar', + secretToken: 'bar', + checked: undefined, + }, + ]); + }); + it('selects policy elastic agent on cloud when available', () => { + const data: APIResponseType = { + agents: [policyElasticAgentOnCloud, ...agents], + cloudStandaloneSetup: undefined, + hasPolicyElasticOnCloud: true, + }; + const options = getEnvironmentConfigurationOptions({ + isCloudEnabled: true, + data, + }); + expect(options).toEqual([ + { + key: 'onPrem_standalone', + label: 'Default Standalone configuration', + apmServerUrl: 'http://localhost:8200', + secretToken: '', + checked: undefined, + }, + { + key: '3', + label: 'policy-elastic-agent-on-cloud', + apmServerUrl: 'baz', + secretToken: 'baz', + checked: 'on', + }, + { + key: '1', + label: 'agent foo', + apmServerUrl: 'foo', + secretToken: 'foo', + checked: undefined, + }, + { + key: '2', + label: 'agent bar', + apmServerUrl: 'bar', + secretToken: 'bar', + checked: undefined, + }, + ]); + }); + }); + }); + describe('Running on prem', () => { + it('shows apm on prem standalone option', () => { + const data: APIResponseType = { + agents: [], + cloudStandaloneSetup: undefined, + hasPolicyElasticOnCloud: false, + }; + const options = getEnvironmentConfigurationOptions({ + isCloudEnabled: false, + data, + }); + expect(options).toEqual([ + { + key: 'onPrem_standalone', + label: 'Default Standalone configuration', + apmServerUrl: 'http://localhost:8200', + secretToken: '', + checked: 'on', + }, + ]); + }); + it('shows apm on prem standalone option and fleet agents options', () => { + const data: APIResponseType = { + agents, + cloudStandaloneSetup: undefined, + hasPolicyElasticOnCloud: false, + }; + const options = getEnvironmentConfigurationOptions({ + isCloudEnabled: false, + data, + }); + expect(options).toEqual([ + { + key: 'onPrem_standalone', + label: 'Default Standalone configuration', + apmServerUrl: 'http://localhost:8200', + secretToken: '', + checked: 'on', + }, + { + key: '1', + label: 'agent foo', + apmServerUrl: 'foo', + secretToken: 'foo', + checked: undefined, + }, + { + key: '2', + label: 'agent bar', + apmServerUrl: 'bar', + secretToken: 'bar', + checked: undefined, + }, + ]); + }); + }); + }); +}); diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/index.tsx b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/index.tsx index b6e882a7a48ef0..290ee78bd1e948 100644 --- a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/index.tsx @@ -5,25 +5,26 @@ * 2.0. */ import { - EuiButton, - EuiButtonEmpty, EuiCodeBlock, EuiFlexGroup, EuiFlexItem, EuiLoadingSpinner, - EuiPopover, - EuiPopoverFooter, - EuiPopoverTitle, - EuiSelectable, EuiSpacer, } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import { HttpStart } from 'kibana/public'; -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useMemo, useState } from 'react'; import styled from 'styled-components'; import { APIReturnType } from '../../../../services/rest/createCallApmApi'; import { CopyCommands } from '../copy_commands'; +import { + EnvironmentConfigurationOption, + EnvironmentConfigurationSelector, +} from './environment_configuration_selector'; import { getCommands } from './commands/get_commands'; +const POLICY_ELASTIC_AGENT_ON_CLOUD = 'policy-elastic-agent-on-cloud'; + interface Props { variantId: string; http: HttpStart; @@ -37,29 +38,71 @@ const CentralizedContainer = styled.div` align-items: center; `; -const onPremStandaloneOption = { - key: 'onPrem_standalone', - label: 'Default Standalone configuration', - apmServerUrl: 'http://localhost:8200', - secretKey: '', - checked: 'on', -}; - type APIResponseType = APIReturnType<'GET /api/apm/fleet/agents'>; -const INITIAL_STATE: APIResponseType = { - agentsCredentials: [], - cloudAgentPolicyCredential: undefined, - cloudCredentials: undefined, -}; - -type SelectValuesType = 'onPrem_standalone' | 'cloud_standalone' | string; - -interface Credential { - key: string; - label: string; - apmServerUrl?: string; - secretToken?: string; - checked?: 'on'; + +const DEFAULT_STANDALONE_CONFIG_LABEL = i18n.translate( + 'xpack.apm.tutorial.agent_config.defaultStandaloneConfig', + { defaultMessage: 'Default Standalone configuration' } +); + +const MANAGE_FLEET_POLICIES_LABEL = i18n.translate( + 'xpack.apm.tutorial.agent_config.manageFleetPolicies', + { defaultMessage: 'Manage fleet policies' } +); + +const GET_STARTED_WITH_FLEET_LABEL = i18n.translate( + 'xpack.apm.tutorial.agent_config.getStartedWithFleet', + { defaultMessage: 'Get started with fleet' } +); + +export function getEnvironmentConfigurationOptions({ + isCloudEnabled, + data, +}: { + isCloudEnabled: boolean; + data: APIResponseType; +}) { + const newOptions: EnvironmentConfigurationOption[] = []; + // When running on cloud and apm.url is defined + if (isCloudEnabled && data.cloudStandaloneSetup?.apmServerUrl) { + // pushes APM cloud standalone + newOptions.push({ + key: 'cloud_standalone', + label: DEFAULT_STANDALONE_CONFIG_LABEL, + apmServerUrl: data.cloudStandaloneSetup?.apmServerUrl, + secretToken: data.cloudStandaloneSetup?.secretToken, + checked: data.hasPolicyElasticOnCloud ? undefined : 'on', + }); + } else { + // pushes APM onprem standalone + newOptions.push({ + key: 'onPrem_standalone', + label: DEFAULT_STANDALONE_CONFIG_LABEL, + apmServerUrl: 'http://localhost:8200', + secretToken: '', + checked: data.hasPolicyElasticOnCloud ? undefined : 'on', + }); + } + + // remaining agents with APM integration + newOptions.push( + ...data.agents.map( + ({ + id, + name, + apmServerUrl, + secretToken, + }): EnvironmentConfigurationOption => ({ + key: id, + label: name, + apmServerUrl, + secretToken, + checked: name === POLICY_ELASTIC_AGENT_ON_CLOUD ? 'on' : undefined, + }) + ) + ); + + return newOptions; } function TutorialAgentSecretTokenSelector({ @@ -68,16 +111,16 @@ function TutorialAgentSecretTokenSelector({ basePath, isCloudEnabled, }: Props) { - const [isPopoverOpen, setIsPopoverOpen] = useState(false); - const [data, setData] = useState(INITIAL_STATE); + const [data, setData] = useState({ + agents: [], + hasPolicyElasticOnCloud: false, + cloudStandaloneSetup: undefined, + }); const [isLoading, setIsLoading] = useState(true); - const [options, setOptions] = useState([]); - const [option, setOption] = useState(); - - useEffect(() => { - const checkedOption = options.find(({ checked }) => checked === 'on'); - setOption(checkedOption); - }, [options]); + const [ + selectedOption, + setSelectedOption, + ] = useState(); useEffect(() => { async function fetchData() { @@ -93,50 +136,9 @@ function TutorialAgentSecretTokenSelector({ fetchData(); }, [http]); - useEffect(() => { - const newOptions = []; - if (isCloudEnabled) { - // has Elastic Cloud managed policy - if (data.cloudAgentPolicyCredential) { - const { - id, - name, - apmServerUrl, - secretToken, - } = data.cloudAgentPolicyCredential; - newOptions.push({ - key: id, - label: name, - apmServerUrl, - secretToken, - checked: 'on', - }); - } else { - // adds standalone cloud - newOptions.push({ - key: 'cloud_standalone', - label: 'Default Standalone configuration', - apmServerUrl: data.cloudCredentials?.apmServerUrl, - secretToken: data.cloudCredentials?.secretToken, - checked: 'on', - }); - } - } else { - // when onPrem - newOptions.push(onPremStandaloneOption); - } - - newOptions.push( - ...data.agentsCredentials?.map( - ({ id, name, apmServerUrl, secretToken }) => ({ - key: id, - label: name, - apmServerUrl, - secretToken, - }) - ) - ); - setOptions(newOptions); + // Depending the environment running (onPrem/Cloud) different values must be available and automatically selected + const options = useMemo(() => { + return getEnvironmentConfigurationOptions({ isCloudEnabled, data }); }, [data, isCloudEnabled]); if (isLoading) { @@ -150,52 +152,34 @@ function TutorialAgentSecretTokenSelector({ const command = getCommands({ variantId, environmentDetails: { - apmServerUrl: option?.apmServerUrl, - secretToken: option?.secretToken, + apmServerUrl: selectedOption?.apmServerUrl, + secretToken: selectedOption?.secretToken, }, }); - function toggleIsPopoverOpen() { - setIsPopoverOpen((state) => !state); - } + const hasFleetAgents = !!data.agents.length; + const fleetLink = hasFleetAgents + ? { + label: MANAGE_FLEET_POLICIES_LABEL, + href: `${basePath}/app/fleet#/policies`, + } + : { + label: GET_STARTED_WITH_FLEET_LABEL, + href: `${basePath}/app/fleet#/integrations/detail/apm-0.2.0/overview`, + }; return ( <> - - {option?.label} - + + setSelectedOption(newSelectedOption) } - isOpen={isPopoverOpen} - closePopover={toggleIsPopoverOpen} - > - setOptions(newOptions)} - singleSelection - > - {(list, search) => ( -
- {search} - {list} - - - Manage this list - - -
- )} -
-
+ fleetLink={fleetLink} + />
diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/copy_commands.tsx b/x-pack/plugins/apm/public/components/shared/tutorial/copy_commands.tsx index 9e02efef059194..c5261cfc1dc042 100644 --- a/x-pack/plugins/apm/public/components/shared/tutorial/copy_commands.tsx +++ b/x-pack/plugins/apm/public/components/shared/tutorial/copy_commands.tsx @@ -5,6 +5,7 @@ * 2.0. */ import { EuiButton, EuiCopy } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import React from 'react'; interface Props { @@ -15,7 +16,9 @@ export function CopyCommands({ commands }: Props) { {(copy) => ( - Copy snippet + {i18n.translate('xpack.apm.tutorial.copySnippet', { + defaultMessage: 'Copy snippet', + })} )} diff --git a/x-pack/plugins/apm/server/routes/fleet.ts b/x-pack/plugins/apm/server/routes/fleet.ts index 3e2d63a5e70e41..3e16228ef1b99b 100644 --- a/x-pack/plugins/apm/server/routes/fleet.ts +++ b/x-pack/plugins/apm/server/routes/fleet.ts @@ -6,7 +6,6 @@ */ import { keyBy } from 'lodash'; -import { AgentPolicy, PackagePolicy } from '../../../fleet/common'; import { getFleetAgents } from '../lib/fleet/get_agents'; import { getApmPackgePolicies } from '../lib/fleet/get_apm_package_policies'; import { createApmServerRoute } from './create_apm_server_route'; @@ -27,27 +26,12 @@ const hasFleetDataRoute = createApmServerRoute({ }, }); -function getAgentPolicyCredentials( - agent: AgentPolicy, - policiesGroupedById: Record -) { - const packagePolicy = policiesGroupedById[agent.id]; - const apmServerCompiledInputs = - packagePolicy.inputs[0].compiled_input['apm-server']; - return { - id: agent.id, - name: agent.name, - apmServerUrl: apmServerCompiledInputs?.host, - secretToken: apmServerCompiledInputs?.secret_token, - }; -} - const fleetAgentsRoute = createApmServerRoute({ endpoint: 'GET /api/apm/fleet/agents', options: { tags: [] }, handler: async ({ core, plugins }) => { const cloudSetup = plugins.cloud?.setup; - const cloudCredentials = cloudSetup + const cloudStandaloneSetup = cloudSetup ? { apmServerUrl: cloudSetup?.apm.url, secretToken: cloudSetup?.apm.secretToken, @@ -70,17 +54,23 @@ const fleetAgentsRoute = createApmServerRoute({ fleetPluginStart, }); - const cloudAgentPolicy = agents.find( + const hasPolicyElasticOnCloud = agents.some( ({ name }) => name === POLICY_ELASTIC_AGENT_ON_CLOUD ); return { - cloudAgentPolicyCredential: cloudAgentPolicy - ? getAgentPolicyCredentials(cloudAgentPolicy, policiesGroupedById) - : undefined, - cloudCredentials, - agentsCredentials: agents.map((agent) => { - return getAgentPolicyCredentials(agent, policiesGroupedById); + hasPolicyElasticOnCloud, + cloudStandaloneSetup, + agents: agents.map((agent) => { + const packagePolicy = policiesGroupedById[agent.id]; + const apmServerCompiledInputs = + packagePolicy.inputs[0].compiled_input['apm-server']; + return { + id: agent.id, + name: agent.name, + apmServerUrl: apmServerCompiledInputs?.host, + secretToken: apmServerCompiledInputs?.secret_token, + }; }), }; }, From 5033edba6ad3682120b70c1bdd7348b68c1a8062 Mon Sep 17 00:00:00 2001 From: cauemarcondes Date: Fri, 18 Jun 2021 16:02:23 -0400 Subject: [PATCH 03/11] adjusting size --- .../config_agent/environment_configuration_selector.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/environment_configuration_selector.tsx b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/environment_configuration_selector.tsx index e22eec6b1ed3ef..bab616ea8f012b 100644 --- a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/environment_configuration_selector.tsx +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/environment_configuration_selector.tsx @@ -84,7 +84,7 @@ export function EnvironmentConfigurationSelector({ isOpen={isPopoverOpen} closePopover={toggleIsPopoverOpen} > -
+
Date: Mon, 21 Jun 2021 15:58:06 -0400 Subject: [PATCH 04/11] refactoring --- .../components/tutorial/instruction.js | 17 +- .../commands/get_commands.test.ts | 536 ++++++++++++++++++ .../config_agent/commands/get_commands.ts | 8 +- .../tutorial/config_agent/commands/java.ts | 4 +- .../tutorial/config_agent/commands/rack.ts | 2 +- .../environment_configuration_selector.tsx | 12 +- .../tutorial/config_agent/index.test.tsx | 27 +- .../shared/tutorial/config_agent/index.tsx | 53 +- .../tutorial/config_agent/rum_script.tsx | 22 +- 9 files changed, 641 insertions(+), 40 deletions(-) create mode 100644 x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/get_commands.test.ts diff --git a/src/plugins/home/public/application/components/tutorial/instruction.js b/src/plugins/home/public/application/components/tutorial/instruction.js index 61aeb221072154..e4b3b3f321bf9e 100644 --- a/src/plugins/home/public/application/components/tutorial/instruction.js +++ b/src/plugins/home/public/application/components/tutorial/instruction.js @@ -18,6 +18,7 @@ import { EuiCopy, EuiButton, EuiLoadingSpinner, + EuiErrorBoundary, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; @@ -100,13 +101,15 @@ export function Instruction({ {LazyCustomComponent && ( }> - + + + )} diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/get_commands.test.ts b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/get_commands.test.ts new file mode 100644 index 00000000000000..e178d1fd0d5176 --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/get_commands.test.ts @@ -0,0 +1,536 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { getCommands } from './get_commands'; + +describe('getCommands', () => { + describe('unknown agent', () => { + it('renders empty command', () => { + const commands = getCommands({ + variantId: 'foo', + environmentDetails: { + apmServerUrl: 'localhost:8220', + secretToken: 'foobar', + }, + }); + expect(commands).toBe(''); + }); + }); + describe('java agent', () => { + it('renders empty commands', () => { + const commands = getCommands({ + variantId: 'java', + environmentDetails: {}, + }); + expect(commands).toMatchInlineSnapshot(` + "java -javaagent:/path/to/elastic-apm-agent-.jar \\\\ + -Delastic.apm.service_name=my-application \\\\ + -Delastic.apm.server_urls= \\\\ + -Delastic.apm.secret_token= \\\\ + -Delastic.apm.environment=production \\\\ + -Delastic.apm.application_packages=org.example \\\\ + -jar my-application.jar" + `); + }); + it('renders with secret token and url', () => { + const commands = getCommands({ + variantId: 'java', + environmentDetails: { + apmServerUrl: 'localhost:8220', + secretToken: 'foobar', + }, + }); + expect(commands).not.toBe(''); + expect(commands).toMatchInlineSnapshot(` + "java -javaagent:/path/to/elastic-apm-agent-.jar \\\\ + -Delastic.apm.service_name=my-application \\\\ + -Delastic.apm.server_urls=localhost:8220 \\\\ + -Delastic.apm.secret_token=foobar \\\\ + -Delastic.apm.environment=production \\\\ + -Delastic.apm.application_packages=org.example \\\\ + -jar my-application.jar" + `); + }); + }); + describe('RUM(js) agent', () => { + it('renders empty commands', () => { + const commands = getCommands({ + variantId: 'js', + environmentDetails: {}, + }); + expect(commands).not.toBe(''); + expect(commands).toMatchInlineSnapshot(` + "import { init as initApm } from '@elastic/apm-rum' + var apm = initApm({ + + // Set required service name (allowed characters: a-z, A-Z, 0-9, -, _, and space) + serviceName: 'your-app-name', + + // Set custom APM Server URL (default: http://localhost:8200) + serverUrl: '', + + // Set the service version (required for source map feature) + serviceVersion: '', + + // Set the service environment + environment: 'production' + })" + `); + }); + it('renders with secret token and url', () => { + const commands = getCommands({ + variantId: 'js', + environmentDetails: { + apmServerUrl: 'localhost:8220', + secretToken: 'foobar', + }, + }); + expect(commands).not.toBe(''); + expect(commands).toMatchInlineSnapshot(` + "import { init as initApm } from '@elastic/apm-rum' + var apm = initApm({ + + // Set required service name (allowed characters: a-z, A-Z, 0-9, -, _, and space) + serviceName: 'your-app-name', + + // Set custom APM Server URL (default: http://localhost:8200) + serverUrl: 'localhost:8220', + + // Set the service version (required for source map feature) + serviceVersion: '', + + // Set the service environment + environment: 'production' + })" + `); + }); + }); + describe('Node.js agent', () => { + it('renders empty commands', () => { + const commands = getCommands({ + variantId: 'node', + environmentDetails: {}, + }); + expect(commands).not.toBe(''); + expect(commands).toMatchInlineSnapshot(` + "// Add this to the VERY top of the first file loaded in your app + var apm = require('elastic-apm-node').start({ + + // Override the service name from package.json + // Allowed characters: a-z, A-Z, 0-9, -, _, and space + serviceName: '', + + // Use if APM Server requires a secret token + secretToken: '', + + // Set the custom APM Server URL (default: http://localhost:8200) + serverUrl: '', + + // Set the service environment + environment: 'production' + })" + `); + }); + it('renders with secret token and url', () => { + const commands = getCommands({ + variantId: 'node', + environmentDetails: { + apmServerUrl: 'localhost:8220', + secretToken: 'foobar', + }, + }); + expect(commands).not.toBe(''); + expect(commands).toMatchInlineSnapshot(` + "// Add this to the VERY top of the first file loaded in your app + var apm = require('elastic-apm-node').start({ + + // Override the service name from package.json + // Allowed characters: a-z, A-Z, 0-9, -, _, and space + serviceName: '', + + // Use if APM Server requires a secret token + secretToken: 'foobar', + + // Set the custom APM Server URL (default: http://localhost:8200) + serverUrl: 'localhost:8220', + + // Set the service environment + environment: 'production' + })" + `); + }); + }); + describe('Django agent', () => { + it('renders empty commands', () => { + const commands = getCommands({ + variantId: 'django', + environmentDetails: {}, + }); + expect(commands).not.toBe(''); + expect(commands).toMatchInlineSnapshot(` + "# Add the agent to the installed apps + INSTALLED_APPS = ( + 'elasticapm.contrib.django', + # ... + ) + + ELASTIC_APM = {curlyOpen} + # Set the required service name. Allowed characters: + # a-z, A-Z, 0-9, -, _, and space + 'SERVICE_NAME': '', + + # Use if APM Server requires a secret token + 'SECRET_TOKEN': '', + + # Set the custom APM Server URL (default: http://localhost:8200) + 'SERVER_URL': '', + + # Set the service environment + 'ENVIRONMENT': 'production', + {curlyClose} + + # To send performance metrics, add our tracing middleware: + MIDDLEWARE = ( + 'elasticapm.contrib.django.middleware.TracingMiddleware', + #... + )" + `); + }); + it('renders with secret token and url', () => { + const commands = getCommands({ + variantId: 'django', + environmentDetails: { + apmServerUrl: 'localhost:8220', + secretToken: 'foobar', + }, + }); + expect(commands).not.toBe(''); + expect(commands).toMatchInlineSnapshot(` + "# Add the agent to the installed apps + INSTALLED_APPS = ( + 'elasticapm.contrib.django', + # ... + ) + + ELASTIC_APM = {curlyOpen} + # Set the required service name. Allowed characters: + # a-z, A-Z, 0-9, -, _, and space + 'SERVICE_NAME': '', + + # Use if APM Server requires a secret token + 'SECRET_TOKEN': 'foobar', + + # Set the custom APM Server URL (default: http://localhost:8200) + 'SERVER_URL': 'localhost:8220', + + # Set the service environment + 'ENVIRONMENT': 'production', + {curlyClose} + + # To send performance metrics, add our tracing middleware: + MIDDLEWARE = ( + 'elasticapm.contrib.django.middleware.TracingMiddleware', + #... + )" + `); + }); + }); + describe('Flask agent', () => { + it('renders empty commands', () => { + const commands = getCommands({ + variantId: 'flask', + environmentDetails: {}, + }); + expect(commands).not.toBe(''); + expect(commands).toMatchInlineSnapshot(` + "# initialize using environment variables + from elasticapm.contrib.flask import ElasticAPM + app = Flask(__name__) + apm = ElasticAPM(app) + + # or configure to use ELASTIC_APM in your application's settings + from elasticapm.contrib.flask import ElasticAPM + app.config['ELASTIC_APM'] = {curlyOpen} + # Set the required service name. Allowed characters: + # a-z, A-Z, 0-9, -, _, and space + 'SERVICE_NAME': '', + + # Use if APM Server requires a secret token + 'SECRET_TOKEN': '', + + # Set the custom APM Server URL (default: http://localhost:8200) + 'SERVER_URL': '', + + # Set the service environment + 'ENVIRONMENT': 'production', + {curlyClose} + + apm = ElasticAPM(app)" + `); + }); + it('renders with secret token and url', () => { + const commands = getCommands({ + variantId: 'flask', + environmentDetails: { + apmServerUrl: 'localhost:8220', + secretToken: 'foobar', + }, + }); + expect(commands).not.toBe(''); + expect(commands).toMatchInlineSnapshot(` + "# initialize using environment variables + from elasticapm.contrib.flask import ElasticAPM + app = Flask(__name__) + apm = ElasticAPM(app) + + # or configure to use ELASTIC_APM in your application's settings + from elasticapm.contrib.flask import ElasticAPM + app.config['ELASTIC_APM'] = {curlyOpen} + # Set the required service name. Allowed characters: + # a-z, A-Z, 0-9, -, _, and space + 'SERVICE_NAME': '', + + # Use if APM Server requires a secret token + 'SECRET_TOKEN': 'foobar', + + # Set the custom APM Server URL (default: http://localhost:8200) + 'SERVER_URL': 'localhost:8220', + + # Set the service environment + 'ENVIRONMENT': 'production', + {curlyClose} + + apm = ElasticAPM(app)" + `); + }); + }); + describe('Ruby on Rails agent', () => { + it('renders empty commands', () => { + const commands = getCommands({ + variantId: 'rails', + environmentDetails: {}, + }); + expect(commands).not.toBe(''); + expect(commands).toMatchInlineSnapshot(` + "# config/elastic_apm.yml: + + # Set the service name - allowed characters: a-z, A-Z, 0-9, -, _ and space + # Defaults to the name of your Rails app + service_name: 'my-service' + + # Use if APM Server requires a secret token + secret_token: '' + + # Set the custom APM Server URL (default: http://localhost:8200) + server_url: '' + + # Set the service environment + environment: 'production'" + `); + }); + it('renders with secret token and url', () => { + const commands = getCommands({ + variantId: 'rails', + environmentDetails: { + apmServerUrl: 'localhost:8220', + secretToken: 'foobar', + }, + }); + expect(commands).not.toBe(''); + expect(commands).toMatchInlineSnapshot(` + "# config/elastic_apm.yml: + + # Set the service name - allowed characters: a-z, A-Z, 0-9, -, _ and space + # Defaults to the name of your Rails app + service_name: 'my-service' + + # Use if APM Server requires a secret token + secret_token: 'foobar' + + # Set the custom APM Server URL (default: http://localhost:8200) + server_url: 'localhost:8220' + + # Set the service environment + environment: 'production'" + `); + }); + }); + describe('Rack agent', () => { + it('renders empty commands', () => { + const commands = getCommands({ + variantId: 'rack', + environmentDetails: {}, + }); + expect(commands).not.toBe(''); + expect(commands).toMatchInlineSnapshot(` + "# config/elastic_apm.yml: + + # Set the service name - allowed characters: a-z, A-Z, 0-9, -, _ and space + # Defaults to the name of your Rack app's class. + service_name: 'my-service' + + # Use if APM Server requires a token + secret_token: '' + + # Set custom APM Server URL (default: http://localhost:8200) + server_url: '', + + # Set the service environment + environment: 'production'" + `); + }); + it('renders with secret token and url', () => { + const commands = getCommands({ + variantId: 'rack', + environmentDetails: { + apmServerUrl: 'localhost:8220', + secretToken: 'foobar', + }, + }); + expect(commands).not.toBe(''); + expect(commands).toMatchInlineSnapshot(` + "# config/elastic_apm.yml: + + # Set the service name - allowed characters: a-z, A-Z, 0-9, -, _ and space + # Defaults to the name of your Rack app's class. + service_name: 'my-service' + + # Use if APM Server requires a token + secret_token: 'foobar' + + # Set custom APM Server URL (default: http://localhost:8200) + server_url: 'localhost:8220', + + # Set the service environment + environment: 'production'" + `); + }); + }); + describe('Go agent', () => { + it('renders empty commands', () => { + const commands = getCommands({ + variantId: 'go', + environmentDetails: {}, + }); + expect(commands).not.toBe(''); + expect(commands).toMatchInlineSnapshot(` + "# Initialize using environment variables: + + # Set the service name. Allowed characters: # a-z, A-Z, 0-9, -, _, and space. + # If ELASTIC_APM_SERVICE_NAME is not specified, the executable name will be used. + export ELASTIC_APM_SERVICE_NAME= + + # Set custom APM Server URL (default: http://localhost:8200) + export ELASTIC_APM_SERVER_URL= + + # Use if APM Server requires a secret token + export ELASTIC_APM_SECRET_TOKEN= + + # Set the service environment + export ELASTIC_APM_ENVIRONMENT= + " + `); + }); + it('renders with secret token and url', () => { + const commands = getCommands({ + variantId: 'go', + environmentDetails: { + apmServerUrl: 'localhost:8220', + secretToken: 'foobar', + }, + }); + expect(commands).not.toBe(''); + expect(commands).toMatchInlineSnapshot(` + "# Initialize using environment variables: + + # Set the service name. Allowed characters: # a-z, A-Z, 0-9, -, _, and space. + # If ELASTIC_APM_SERVICE_NAME is not specified, the executable name will be used. + export ELASTIC_APM_SERVICE_NAME= + + # Set custom APM Server URL (default: http://localhost:8200) + export ELASTIC_APM_SERVER_URL=localhost:8220 + + # Use if APM Server requires a secret token + export ELASTIC_APM_SECRET_TOKEN=foobar + + # Set the service environment + export ELASTIC_APM_ENVIRONMENT= + " + `); + }); + }); + describe('dotNet agent', () => { + it('renders empty commands', () => { + const commands = getCommands({ + variantId: 'dotnet', + environmentDetails: {}, + }); + expect(commands).not.toBe(''); + expect(commands).toMatchInlineSnapshot(` + "{ + \\"ElasticApm\\": { + \\"SecretToken\\": \\"\\", + \\"ServerUrls\\": \\"\\", //Set custom APM Server URL (default: http://localhost:8200) + \\"ServiceName\\": \\"MyApp\\", //allowed characters: a-z, A-Z, 0-9, -, _, and space. Default is the entry assembly of the application + \\"Environment\\": \\"production\\", // Set the service environment + } + }" + `); + }); + it('renders with secret token and url', () => { + const commands = getCommands({ + variantId: 'dotnet', + environmentDetails: { + apmServerUrl: 'localhost:8220', + secretToken: 'foobar', + }, + }); + expect(commands).not.toBe(''); + expect(commands).toMatchInlineSnapshot(` + "{ + \\"ElasticApm\\": { + \\"SecretToken\\": \\"foobar\\", + \\"ServerUrls\\": \\"localhost:8220\\", //Set custom APM Server URL (default: http://localhost:8200) + \\"ServiceName\\": \\"MyApp\\", //allowed characters: a-z, A-Z, 0-9, -, _, and space. Default is the entry assembly of the application + \\"Environment\\": \\"production\\", // Set the service environment + } + }" + `); + }); + }); + describe('PHP agent', () => { + it('renders empty commands', () => { + const commands = getCommands({ + variantId: 'php', + environmentDetails: {}, + }); + expect(commands).not.toBe(''); + expect(commands).toMatchInlineSnapshot(` + "elastic_apm.server_url=\\"\\" + elastic.apm.secret_token=\\"\\" + elastic_apm.service_name=\\"My service\\" + " + `); + }); + it('renders with secret token and url', () => { + const commands = getCommands({ + variantId: 'php', + environmentDetails: { + apmServerUrl: 'localhost:8220', + secretToken: 'foobar', + }, + }); + expect(commands).not.toBe(''); + expect(commands).toMatchInlineSnapshot(` + "elastic_apm.server_url=\\"localhost:8220\\" + elastic.apm.secret_token=\\"foobar\\" + elastic_apm.service_name=\\"My service\\" + " + `); + }); + }); +}); diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/get_commands.ts b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/get_commands.ts index 5fa869b019f246..b76c5f37cb001a 100644 --- a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/get_commands.ts +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/get_commands.ts @@ -16,7 +16,7 @@ import { dotnet } from './dotnet'; import { php } from './php'; import { rum, rumScript } from './rum'; -const commands: Record = { +const commandsMap: Record = { java, node, django, @@ -40,5 +40,9 @@ export function getCommands({ secretToken?: string; }; }) { - return Mustache.render(commands[variantId], environmentDetails); + const commands = commandsMap[variantId]; + if (!commands) { + return ''; + } + return Mustache.render(commands, environmentDetails); } diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/java.ts b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/java.ts index 28590f889b4a4b..249907a9b0c4bf 100644 --- a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/java.ts +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/java.ts @@ -7,8 +7,8 @@ export const java = `java -javaagent:/path/to/elastic-apm-agent-.jar \\ -Delastic.apm.service_name=my-application \\ --Delastic.apm.server_urls= {{{apmServerUrl}}} \\ --Delastic.apm.secret_token= {{{{secretToken}}}} \\ +-Delastic.apm.server_urls={{{apmServerUrl}}} \\ +-Delastic.apm.secret_token={{{secretToken}}} \\ -Delastic.apm.environment=production \\ -Delastic.apm.application_packages=org.example \\ -jar my-application.jar`; diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/rack.ts b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/rack.ts index 7adf99366f615d..9195ad9f156666 100644 --- a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/rack.ts +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/rack.ts @@ -39,7 +39,7 @@ secret_token: '{{{secretToken}}}' values: { defaultServerUrl: 'http://localhost:8200' }, } )} -server_url: {{{apmServerUrl}}}, +server_url: '{{{apmServerUrl}}}', # ${i18n.translate( 'xpack.apm.tutorial.rackClient.createConfig.commands.setServiceEnvironment', diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/environment_configuration_selector.tsx b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/environment_configuration_selector.tsx index bab616ea8f012b..745e6cd0ec70b4 100644 --- a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/environment_configuration_selector.tsx +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/environment_configuration_selector.tsx @@ -13,21 +13,21 @@ import { EuiPopoverFooter, EuiPopoverTitle, EuiSelectable, + EuiSelectableOption, + EuiButton, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React, { useEffect, useState } from 'react'; import styled from 'styled-components'; import { px } from '../../../../style/variables'; -export interface EnvironmentConfigurationOption { - key: string; - label: string; +export type EnvironmentConfigurationOption = EuiSelectableOption & { apmServerUrl?: string; secretToken?: string; checked?: 'on'; -} +}; -const StyledEuiButtomEmpty = styled(EuiButtonEmpty)` +const StyledEuiButtomEmpty = styled(EuiButton)` .euiButtonContent { display: flex; justify-content: space-between; @@ -70,6 +70,7 @@ export function EnvironmentConfigurationSelector({ return ( ; @@ -79,6 +79,11 @@ describe('Tutorial config agent', () => { secretToken: 'bar', checked: 'on', }, + { + isGroupLabel: true, + key: 'fleet_policies', + label: 'Fleet policies', + }, { key: '1', label: 'agent foo', @@ -116,6 +121,11 @@ describe('Tutorial config agent', () => { secretToken: 'bar', checked: undefined, }, + { + isGroupLabel: true, + key: 'fleet_policies', + label: 'Fleet policies', + }, { key: '3', label: 'policy-elastic-agent-on-cloud', @@ -179,6 +189,11 @@ describe('Tutorial config agent', () => { secretToken: '', checked: 'on', }, + { + isGroupLabel: true, + key: 'fleet_policies', + label: 'Fleet policies', + }, { key: '1', label: 'agent foo', @@ -213,6 +228,11 @@ describe('Tutorial config agent', () => { secretToken: '', checked: undefined, }, + { + isGroupLabel: true, + key: 'fleet_policies', + label: 'Fleet policies', + }, { key: '3', label: 'policy-elastic-agent-on-cloud', @@ -277,6 +297,11 @@ describe('Tutorial config agent', () => { secretToken: '', checked: 'on', }, + { + isGroupLabel: true, + key: 'fleet_policies', + label: 'Fleet policies', + }, { key: '1', label: 'agent foo', diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/index.tsx b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/index.tsx index 290ee78bd1e948..34719e3f0a712d 100644 --- a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/index.tsx @@ -84,23 +84,34 @@ export function getEnvironmentConfigurationOptions({ }); } - // remaining agents with APM integration - newOptions.push( - ...data.agents.map( - ({ - id, - name, - apmServerUrl, - secretToken, - }): EnvironmentConfigurationOption => ({ - key: id, - label: name, - apmServerUrl, - secretToken, - checked: name === POLICY_ELASTIC_AGENT_ON_CLOUD ? 'on' : undefined, - }) - ) - ); + if (data.agents.length) { + // Adds fleet policies group label + newOptions.push({ + key: 'fleet_policies', + label: i18n.translate( + 'xpack.apm.tutorial.agent_config.fleetPoliciesLabel', + { defaultMessage: 'Fleet policies' } + ), + isGroupLabel: true, + }); + // remaining agents with APM integration + newOptions.push( + ...data.agents.map( + ({ + id, + name, + apmServerUrl, + secretToken, + }): EnvironmentConfigurationOption => ({ + key: id, + label: name, + apmServerUrl, + secretToken, + checked: name === POLICY_ELASTIC_AGENT_ON_CLOUD ? 'on' : undefined, + }) + ) + ); + } return newOptions; } @@ -149,7 +160,7 @@ function TutorialAgentSecretTokenSelector({ ); } - const command = getCommands({ + const commands = getCommands({ variantId, environmentDetails: { apmServerUrl: selectedOption?.apmServerUrl, @@ -182,11 +193,13 @@ function TutorialAgentSecretTokenSelector({ /> - + - {command} + + {commands} + ); } diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/rum_script.tsx b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/rum_script.tsx index ac9ca53bdee6cf..4b8cdcc932fe76 100644 --- a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/rum_script.tsx +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/rum_script.tsx @@ -4,11 +4,29 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ +import { HttpStart } from 'kibana/public'; import React from 'react'; import TutorialAgentSecretTokenSelector from './'; -function TutorialConfigAgentRumScript() { - return ; +interface Props { + http: HttpStart; + basePath: string; + isCloudEnabled: boolean; +} + +function TutorialConfigAgentRumScript({ + http, + basePath, + isCloudEnabled, +}: Props) { + return ( + + ); } // eslint-disable-next-line import/no-default-export From 585dcb9bb3872dad40aa7a10de74787bc8a94324 Mon Sep 17 00:00:00 2001 From: cauemarcondes Date: Tue, 22 Jun 2021 13:17:43 -0400 Subject: [PATCH 05/11] refactoring eui component --- .../commands/get_commands.test.ts | 42 +-- .../config_agent/commands/get_commands.ts | 6 +- .../environment_configuration_selector.tsx | 134 ------- .../config_agent/get_policy_options.test.ts | 342 ++++++++++++++++++ .../config_agent/get_policy_options.ts | 76 ++++ .../tutorial/config_agent/index.test.tsx | 317 ---------------- .../shared/tutorial/config_agent/index.tsx | 103 +----- .../tutorial/config_agent/policy_selector.tsx | 62 ++++ x-pack/plugins/apm/server/routes/fleet.ts | 5 - 9 files changed, 521 insertions(+), 566 deletions(-) delete mode 100644 x-pack/plugins/apm/public/components/shared/tutorial/config_agent/environment_configuration_selector.tsx create mode 100644 x-pack/plugins/apm/public/components/shared/tutorial/config_agent/get_policy_options.test.ts create mode 100644 x-pack/plugins/apm/public/components/shared/tutorial/config_agent/get_policy_options.ts create mode 100644 x-pack/plugins/apm/public/components/shared/tutorial/config_agent/policy_selector.tsx diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/get_commands.test.ts b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/get_commands.test.ts index e178d1fd0d5176..5dc66e22305248 100644 --- a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/get_commands.test.ts +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/get_commands.test.ts @@ -12,7 +12,7 @@ describe('getCommands', () => { it('renders empty command', () => { const commands = getCommands({ variantId: 'foo', - environmentDetails: { + policyDetails: { apmServerUrl: 'localhost:8220', secretToken: 'foobar', }, @@ -24,7 +24,7 @@ describe('getCommands', () => { it('renders empty commands', () => { const commands = getCommands({ variantId: 'java', - environmentDetails: {}, + policyDetails: {}, }); expect(commands).toMatchInlineSnapshot(` "java -javaagent:/path/to/elastic-apm-agent-.jar \\\\ @@ -39,7 +39,7 @@ describe('getCommands', () => { it('renders with secret token and url', () => { const commands = getCommands({ variantId: 'java', - environmentDetails: { + policyDetails: { apmServerUrl: 'localhost:8220', secretToken: 'foobar', }, @@ -60,7 +60,7 @@ describe('getCommands', () => { it('renders empty commands', () => { const commands = getCommands({ variantId: 'js', - environmentDetails: {}, + policyDetails: {}, }); expect(commands).not.toBe(''); expect(commands).toMatchInlineSnapshot(` @@ -84,7 +84,7 @@ describe('getCommands', () => { it('renders with secret token and url', () => { const commands = getCommands({ variantId: 'js', - environmentDetails: { + policyDetails: { apmServerUrl: 'localhost:8220', secretToken: 'foobar', }, @@ -113,7 +113,7 @@ describe('getCommands', () => { it('renders empty commands', () => { const commands = getCommands({ variantId: 'node', - environmentDetails: {}, + policyDetails: {}, }); expect(commands).not.toBe(''); expect(commands).toMatchInlineSnapshot(` @@ -138,7 +138,7 @@ describe('getCommands', () => { it('renders with secret token and url', () => { const commands = getCommands({ variantId: 'node', - environmentDetails: { + policyDetails: { apmServerUrl: 'localhost:8220', secretToken: 'foobar', }, @@ -168,7 +168,7 @@ describe('getCommands', () => { it('renders empty commands', () => { const commands = getCommands({ variantId: 'django', - environmentDetails: {}, + policyDetails: {}, }); expect(commands).not.toBe(''); expect(commands).toMatchInlineSnapshot(` @@ -203,7 +203,7 @@ describe('getCommands', () => { it('renders with secret token and url', () => { const commands = getCommands({ variantId: 'django', - environmentDetails: { + policyDetails: { apmServerUrl: 'localhost:8220', secretToken: 'foobar', }, @@ -243,7 +243,7 @@ describe('getCommands', () => { it('renders empty commands', () => { const commands = getCommands({ variantId: 'flask', - environmentDetails: {}, + policyDetails: {}, }); expect(commands).not.toBe(''); expect(commands).toMatchInlineSnapshot(` @@ -275,7 +275,7 @@ describe('getCommands', () => { it('renders with secret token and url', () => { const commands = getCommands({ variantId: 'flask', - environmentDetails: { + policyDetails: { apmServerUrl: 'localhost:8220', secretToken: 'foobar', }, @@ -312,7 +312,7 @@ describe('getCommands', () => { it('renders empty commands', () => { const commands = getCommands({ variantId: 'rails', - environmentDetails: {}, + policyDetails: {}, }); expect(commands).not.toBe(''); expect(commands).toMatchInlineSnapshot(` @@ -335,7 +335,7 @@ describe('getCommands', () => { it('renders with secret token and url', () => { const commands = getCommands({ variantId: 'rails', - environmentDetails: { + policyDetails: { apmServerUrl: 'localhost:8220', secretToken: 'foobar', }, @@ -363,7 +363,7 @@ describe('getCommands', () => { it('renders empty commands', () => { const commands = getCommands({ variantId: 'rack', - environmentDetails: {}, + policyDetails: {}, }); expect(commands).not.toBe(''); expect(commands).toMatchInlineSnapshot(` @@ -386,7 +386,7 @@ describe('getCommands', () => { it('renders with secret token and url', () => { const commands = getCommands({ variantId: 'rack', - environmentDetails: { + policyDetails: { apmServerUrl: 'localhost:8220', secretToken: 'foobar', }, @@ -414,7 +414,7 @@ describe('getCommands', () => { it('renders empty commands', () => { const commands = getCommands({ variantId: 'go', - environmentDetails: {}, + policyDetails: {}, }); expect(commands).not.toBe(''); expect(commands).toMatchInlineSnapshot(` @@ -438,7 +438,7 @@ describe('getCommands', () => { it('renders with secret token and url', () => { const commands = getCommands({ variantId: 'go', - environmentDetails: { + policyDetails: { apmServerUrl: 'localhost:8220', secretToken: 'foobar', }, @@ -467,7 +467,7 @@ describe('getCommands', () => { it('renders empty commands', () => { const commands = getCommands({ variantId: 'dotnet', - environmentDetails: {}, + policyDetails: {}, }); expect(commands).not.toBe(''); expect(commands).toMatchInlineSnapshot(` @@ -484,7 +484,7 @@ describe('getCommands', () => { it('renders with secret token and url', () => { const commands = getCommands({ variantId: 'dotnet', - environmentDetails: { + policyDetails: { apmServerUrl: 'localhost:8220', secretToken: 'foobar', }, @@ -506,7 +506,7 @@ describe('getCommands', () => { it('renders empty commands', () => { const commands = getCommands({ variantId: 'php', - environmentDetails: {}, + policyDetails: {}, }); expect(commands).not.toBe(''); expect(commands).toMatchInlineSnapshot(` @@ -519,7 +519,7 @@ describe('getCommands', () => { it('renders with secret token and url', () => { const commands = getCommands({ variantId: 'php', - environmentDetails: { + policyDetails: { apmServerUrl: 'localhost:8220', secretToken: 'foobar', }, diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/get_commands.ts b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/get_commands.ts index b76c5f37cb001a..73a388c3f735e7 100644 --- a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/get_commands.ts +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/get_commands.ts @@ -32,10 +32,10 @@ const commandsMap: Record = { export function getCommands({ variantId, - environmentDetails, + policyDetails, }: { variantId: string; - environmentDetails: { + policyDetails: { apmServerUrl?: string; secretToken?: string; }; @@ -44,5 +44,5 @@ export function getCommands({ if (!commands) { return ''; } - return Mustache.render(commands, environmentDetails); + return Mustache.render(commands, policyDetails); } diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/environment_configuration_selector.tsx b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/environment_configuration_selector.tsx deleted file mode 100644 index 745e6cd0ec70b4..00000000000000 --- a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/environment_configuration_selector.tsx +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { - EuiButtonEmpty, - EuiFlexGroup, - EuiFlexItem, - EuiPopover, - EuiPopoverFooter, - EuiPopoverTitle, - EuiSelectable, - EuiSelectableOption, - EuiButton, -} from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import React, { useEffect, useState } from 'react'; -import styled from 'styled-components'; -import { px } from '../../../../style/variables'; - -export type EnvironmentConfigurationOption = EuiSelectableOption & { - apmServerUrl?: string; - secretToken?: string; - checked?: 'on'; -}; - -const StyledEuiButtomEmpty = styled(EuiButton)` - .euiButtonContent { - display: flex; - justify-content: space-between; - } -`; - -interface Props { - options: EnvironmentConfigurationOption[]; - selectedOption?: EnvironmentConfigurationOption; - onChange: (selectedOption?: EnvironmentConfigurationOption) => void; - fleetLink: { - label: string; - href: string; - }; -} - -function findCheckedOption(options: EnvironmentConfigurationOption[]) { - return options.find(({ checked }) => checked === 'on'); -} - -export function EnvironmentConfigurationSelector({ - options, - selectedOption, - onChange, - fleetLink, -}: Props) { - const [isPopoverOpen, setIsPopoverOpen] = useState(false); - const [availableOptions, setAvailableOptions] = useState< - EnvironmentConfigurationOption[] - >(options); - - useEffect(() => { - const checkedOption = findCheckedOption(availableOptions); - onChange(checkedOption); - }, [availableOptions, onChange]); - - function toggleIsPopoverOpen() { - setIsPopoverOpen((state) => !state); - } - - return ( - - {selectedOption?.label} - - } - isOpen={isPopoverOpen} - closePopover={toggleIsPopoverOpen} - > -
- { - const nextSelectedOption = findCheckedOption(newOptions); - // When there is no checked option don't update the options so we always have at least one option selected - if (nextSelectedOption) { - setAvailableOptions(newOptions); - setIsPopoverOpen(false); - } - }} - singleSelection - > - {(list, search) => { - return ( - <> - {search} - {list} - - - - - {fleetLink.label} - - - - - - ); - }} - -
-
- ); -} diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/get_policy_options.test.ts b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/get_policy_options.test.ts new file mode 100644 index 00000000000000..df5583d85b3f26 --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/get_policy_options.test.ts @@ -0,0 +1,342 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { getPolicyOptions } from './get_policy_options'; +import { APIReturnType } from '../../../../services/rest/createCallApmApi'; + +type APIResponseType = APIReturnType<'GET /api/apm/fleet/agents'>; + +const policyElasticAgentOnCloudAgent = { + id: 'policy-elastic-agent-on-cloud', + name: 'Elastic Cloud agent policy', + apmServerUrl: 'apm_cloud_url', + secretToken: 'apm_cloud_token', +}; + +const agents = [ + { + id: '1', + name: 'agent foo', + apmServerUrl: 'foo', + secretToken: 'foo', + }, + { + id: '2', + name: 'agent bar', + apmServerUrl: 'bar', + secretToken: 'bar', + }, +]; + +describe('getPolicyOptions', () => { + describe('running on cloud', () => { + describe('with APM on cloud', () => { + it('shows apm on cloud standalone option', () => { + const data: APIResponseType = { + agents: [], + cloudStandaloneSetup: { + apmServerUrl: 'cloud_url', + secretToken: 'cloud_token', + }, + }; + const { availableOptions, defaultSelectedOption } = getPolicyOptions({ + isCloudEnabled: true, + data, + }); + expect(defaultSelectedOption).toEqual({ + key: 'cloud_standalone', + label: 'Default Standalone configuration', + apmServerUrl: 'cloud_url', + secretToken: 'cloud_token', + }); + expect(availableOptions).toEqual([ + { + key: 'cloud_standalone', + label: 'Default Standalone configuration', + apmServerUrl: 'cloud_url', + secretToken: 'cloud_token', + }, + ]); + }); + it('shows apm on cloud standalone option and fleet agents options', () => { + const data: APIResponseType = { + agents, + cloudStandaloneSetup: { + apmServerUrl: 'cloud_url', + secretToken: 'cloud_token', + }, + }; + const { availableOptions, defaultSelectedOption } = getPolicyOptions({ + isCloudEnabled: true, + data, + }); + expect(defaultSelectedOption).toEqual({ + key: 'cloud_standalone', + label: 'Default Standalone configuration', + apmServerUrl: 'cloud_url', + secretToken: 'cloud_token', + }); + expect(availableOptions).toEqual([ + { + key: 'cloud_standalone', + label: 'Default Standalone configuration', + apmServerUrl: 'cloud_url', + secretToken: 'cloud_token', + }, + { + label: 'Fleet policies', + options: [ + { + key: '1', + label: 'agent foo', + apmServerUrl: 'foo', + secretToken: 'foo', + }, + { + key: '2', + label: 'agent bar', + apmServerUrl: 'bar', + secretToken: 'bar', + }, + ], + }, + ]); + }); + it('selects policy elastic agent on cloud when available', () => { + const data: APIResponseType = { + agents: [policyElasticAgentOnCloudAgent, ...agents], + cloudStandaloneSetup: { + apmServerUrl: 'cloud_url', + secretToken: 'cloud_token', + }, + }; + const { availableOptions, defaultSelectedOption } = getPolicyOptions({ + isCloudEnabled: true, + data, + }); + expect(defaultSelectedOption).toEqual({ + key: 'policy-elastic-agent-on-cloud', + label: 'Elastic Cloud agent policy', + apmServerUrl: 'apm_cloud_url', + secretToken: 'apm_cloud_token', + }); + expect(availableOptions).toEqual([ + { + key: 'cloud_standalone', + label: 'Default Standalone configuration', + apmServerUrl: 'cloud_url', + secretToken: 'cloud_token', + }, + { + label: 'Fleet policies', + options: [ + { + key: 'policy-elastic-agent-on-cloud', + label: 'Elastic Cloud agent policy', + apmServerUrl: 'apm_cloud_url', + secretToken: 'apm_cloud_token', + }, + { + key: '1', + label: 'agent foo', + apmServerUrl: 'foo', + secretToken: 'foo', + }, + { + key: '2', + label: 'agent bar', + apmServerUrl: 'bar', + secretToken: 'bar', + }, + ], + }, + ]); + }); + }); + describe('with APM on prem', () => { + it('shows apm on prem standalone option', () => { + const data: APIResponseType = { + agents: [], + cloudStandaloneSetup: undefined, + }; + const { availableOptions, defaultSelectedOption } = getPolicyOptions({ + isCloudEnabled: true, + data, + }); + expect(defaultSelectedOption).toEqual({ + key: 'onPrem_standalone', + label: 'Default Standalone configuration', + apmServerUrl: 'http://localhost:8200', + secretToken: '', + }); + expect(availableOptions).toEqual([ + { + key: 'onPrem_standalone', + label: 'Default Standalone configuration', + apmServerUrl: 'http://localhost:8200', + secretToken: '', + }, + ]); + }); + it('shows apm on prem standalone option and fleet agents options', () => { + const data: APIResponseType = { + agents, + cloudStandaloneSetup: undefined, + }; + const { availableOptions, defaultSelectedOption } = getPolicyOptions({ + isCloudEnabled: true, + data, + }); + expect(defaultSelectedOption).toEqual({ + key: 'onPrem_standalone', + label: 'Default Standalone configuration', + apmServerUrl: 'http://localhost:8200', + secretToken: '', + }); + expect(availableOptions).toEqual([ + { + key: 'onPrem_standalone', + label: 'Default Standalone configuration', + apmServerUrl: 'http://localhost:8200', + secretToken: '', + }, + { + label: 'Fleet policies', + options: [ + { + key: '1', + label: 'agent foo', + apmServerUrl: 'foo', + secretToken: 'foo', + }, + { + key: '2', + label: 'agent bar', + apmServerUrl: 'bar', + secretToken: 'bar', + }, + ], + }, + ]); + }); + it('selects policy elastic agent on cloud when available', () => { + const data: APIResponseType = { + agents: [policyElasticAgentOnCloudAgent, ...agents], + cloudStandaloneSetup: undefined, + }; + const { availableOptions, defaultSelectedOption } = getPolicyOptions({ + isCloudEnabled: true, + data, + }); + expect(defaultSelectedOption).toEqual({ + key: 'policy-elastic-agent-on-cloud', + label: 'Elastic Cloud agent policy', + apmServerUrl: 'apm_cloud_url', + secretToken: 'apm_cloud_token', + }); + expect(availableOptions).toEqual([ + { + key: 'onPrem_standalone', + label: 'Default Standalone configuration', + apmServerUrl: 'http://localhost:8200', + secretToken: '', + checked: undefined, + }, + { + label: 'Fleet policies', + options: [ + { + key: 'policy-elastic-agent-on-cloud', + label: 'Elastic Cloud agent policy', + apmServerUrl: 'apm_cloud_url', + secretToken: 'apm_cloud_token', + }, + { + key: '1', + label: 'agent foo', + apmServerUrl: 'foo', + secretToken: 'foo', + }, + { + key: '2', + label: 'agent bar', + apmServerUrl: 'bar', + secretToken: 'bar', + }, + ], + }, + ]); + }); + }); + }); + describe('Running on prem', () => { + it('shows apm on prem standalone option', () => { + const data: APIResponseType = { + agents: [], + cloudStandaloneSetup: undefined, + }; + const { availableOptions, defaultSelectedOption } = getPolicyOptions({ + isCloudEnabled: false, + data, + }); + expect(defaultSelectedOption).toEqual({ + key: 'onPrem_standalone', + label: 'Default Standalone configuration', + apmServerUrl: 'http://localhost:8200', + secretToken: '', + }); + expect(availableOptions).toEqual([ + { + key: 'onPrem_standalone', + label: 'Default Standalone configuration', + apmServerUrl: 'http://localhost:8200', + secretToken: '', + }, + ]); + }); + it('shows apm on prem standalone option and fleet agents options', () => { + const data: APIResponseType = { + agents, + cloudStandaloneSetup: undefined, + }; + const { availableOptions, defaultSelectedOption } = getPolicyOptions({ + isCloudEnabled: false, + data, + }); + expect(defaultSelectedOption).toEqual({ + key: 'onPrem_standalone', + label: 'Default Standalone configuration', + apmServerUrl: 'http://localhost:8200', + secretToken: '', + }); + expect(availableOptions).toEqual([ + { + key: 'onPrem_standalone', + label: 'Default Standalone configuration', + apmServerUrl: 'http://localhost:8200', + secretToken: '', + }, + { + label: 'Fleet policies', + options: [ + { + key: '1', + label: 'agent foo', + apmServerUrl: 'foo', + secretToken: 'foo', + }, + { + key: '2', + label: 'agent bar', + apmServerUrl: 'bar', + secretToken: 'bar', + }, + ], + }, + ]); + }); + }); +}); diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/get_policy_options.ts b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/get_policy_options.ts new file mode 100644 index 00000000000000..d56d7bda4070f5 --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/get_policy_options.ts @@ -0,0 +1,76 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { i18n } from '@kbn/i18n'; +import { APIResponseType } from './'; +import { PolicySelectorOption } from './policy_selector'; + +const POLICY_ELASTIC_AGENT_ON_CLOUD = 'policy-elastic-agent-on-cloud'; + +const DEFAULT_STANDALONE_CONFIG_LABEL = i18n.translate( + 'xpack.apm.tutorial.agent_config.defaultStandaloneConfig', + { defaultMessage: 'Default Standalone configuration' } +); + +const onPremStandaloneOption = { + key: 'onPrem_standalone', + label: DEFAULT_STANDALONE_CONFIG_LABEL, + apmServerUrl: 'http://localhost:8200', + secretToken: '', +}; + +export function getPolicyOptions({ + isCloudEnabled, + data, +}: { + isCloudEnabled: boolean; + data: APIResponseType; +}) { + const availableOptions: PolicySelectorOption[] = []; + let defaultSelectedOption: PolicySelectorOption; + // When running on cloud and apm.url is defined + if (isCloudEnabled && data.cloudStandaloneSetup?.apmServerUrl) { + // pushes APM cloud standalone + const cloudStandaloneOption = { + key: 'cloud_standalone', + label: DEFAULT_STANDALONE_CONFIG_LABEL, + apmServerUrl: data.cloudStandaloneSetup?.apmServerUrl, + secretToken: data.cloudStandaloneSetup?.secretToken, + }; + availableOptions.push(cloudStandaloneOption); + defaultSelectedOption = cloudStandaloneOption; + } else { + // pushes APM onprem standalone + availableOptions.push(onPremStandaloneOption); + defaultSelectedOption = onPremStandaloneOption; + } + + if (data.agents.length) { + // Adds fleet policies group label and remaining agents with APM integration + availableOptions.push({ + label: i18n.translate( + 'xpack.apm.tutorial.agent_config.fleetPoliciesLabel', + { defaultMessage: 'Fleet policies' } + ), + options: data.agents.map( + (agent): PolicySelectorOption => { + const agentOption = { + key: agent.id, + label: agent.name, + apmServerUrl: agent.apmServerUrl, + secretToken: agent.secretToken, + }; + if (agent.id === POLICY_ELASTIC_AGENT_ON_CLOUD) { + defaultSelectedOption = agentOption; + } + return agentOption; + } + ), + }); + } + + return { availableOptions, defaultSelectedOption }; +} diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/index.test.tsx b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/index.test.tsx index fdfcc13f9725b7..1fec1c76430ebd 100644 --- a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/index.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/index.test.tsx @@ -4,320 +4,3 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { APIReturnType } from '../../../../services/rest/createCallApmApi'; -import { getEnvironmentConfigurationOptions } from './'; - -type APIResponseType = APIReturnType<'GET /api/apm/fleet/agents'>; - -const policyElasticAgentOnCloud = { - id: '3', - name: 'policy-elastic-agent-on-cloud', - apmServerUrl: 'baz', - secretToken: 'baz', -}; - -const agents = [ - { - id: '1', - name: 'agent foo', - apmServerUrl: 'foo', - secretToken: 'foo', - }, - { - id: '2', - name: 'agent bar', - apmServerUrl: 'bar', - secretToken: 'bar', - }, -]; - -describe('Tutorial config agent', () => { - describe('getEnvironmentConfigurationOptions', () => { - describe('running on cloud', () => { - describe('with APM on cloud', () => { - it('shows apm on cloud standalone option', () => { - const data: APIResponseType = { - agents: [], - cloudStandaloneSetup: { - apmServerUrl: 'foo', - secretToken: 'bar', - }, - hasPolicyElasticOnCloud: false, - }; - const options = getEnvironmentConfigurationOptions({ - isCloudEnabled: true, - data, - }); - expect(options).toEqual([ - { - key: 'cloud_standalone', - label: 'Default Standalone configuration', - apmServerUrl: 'foo', - secretToken: 'bar', - checked: 'on', - }, - ]); - }); - it('shows apm on cloud standalone option and fleet agents options', () => { - const data: APIResponseType = { - agents, - cloudStandaloneSetup: { - apmServerUrl: 'foo', - secretToken: 'bar', - }, - hasPolicyElasticOnCloud: false, - }; - const options = getEnvironmentConfigurationOptions({ - isCloudEnabled: true, - data, - }); - expect(options).toEqual([ - { - key: 'cloud_standalone', - label: 'Default Standalone configuration', - apmServerUrl: 'foo', - secretToken: 'bar', - checked: 'on', - }, - { - isGroupLabel: true, - key: 'fleet_policies', - label: 'Fleet policies', - }, - { - key: '1', - label: 'agent foo', - apmServerUrl: 'foo', - secretToken: 'foo', - checked: undefined, - }, - { - key: '2', - label: 'agent bar', - apmServerUrl: 'bar', - secretToken: 'bar', - checked: undefined, - }, - ]); - }); - it('selects policy elastic agent on cloud when available', () => { - const data: APIResponseType = { - agents: [policyElasticAgentOnCloud, ...agents], - cloudStandaloneSetup: { - apmServerUrl: 'foo', - secretToken: 'bar', - }, - hasPolicyElasticOnCloud: true, - }; - const options = getEnvironmentConfigurationOptions({ - isCloudEnabled: true, - data, - }); - expect(options).toEqual([ - { - key: 'cloud_standalone', - label: 'Default Standalone configuration', - apmServerUrl: 'foo', - secretToken: 'bar', - checked: undefined, - }, - { - isGroupLabel: true, - key: 'fleet_policies', - label: 'Fleet policies', - }, - { - key: '3', - label: 'policy-elastic-agent-on-cloud', - apmServerUrl: 'baz', - secretToken: 'baz', - checked: 'on', - }, - { - key: '1', - label: 'agent foo', - apmServerUrl: 'foo', - secretToken: 'foo', - checked: undefined, - }, - { - key: '2', - label: 'agent bar', - apmServerUrl: 'bar', - secretToken: 'bar', - checked: undefined, - }, - ]); - }); - }); - describe('with APM on prem', () => { - it('shows apm on prem standalone option', () => { - const data: APIResponseType = { - agents: [], - cloudStandaloneSetup: undefined, - hasPolicyElasticOnCloud: false, - }; - const options = getEnvironmentConfigurationOptions({ - isCloudEnabled: true, - data, - }); - expect(options).toEqual([ - { - key: 'onPrem_standalone', - label: 'Default Standalone configuration', - apmServerUrl: 'http://localhost:8200', - secretToken: '', - checked: 'on', - }, - ]); - }); - it('shows apm on prem standalone option and fleet agents options', () => { - const data: APIResponseType = { - agents, - cloudStandaloneSetup: undefined, - hasPolicyElasticOnCloud: false, - }; - const options = getEnvironmentConfigurationOptions({ - isCloudEnabled: true, - data, - }); - expect(options).toEqual([ - { - key: 'onPrem_standalone', - label: 'Default Standalone configuration', - apmServerUrl: 'http://localhost:8200', - secretToken: '', - checked: 'on', - }, - { - isGroupLabel: true, - key: 'fleet_policies', - label: 'Fleet policies', - }, - { - key: '1', - label: 'agent foo', - apmServerUrl: 'foo', - secretToken: 'foo', - checked: undefined, - }, - { - key: '2', - label: 'agent bar', - apmServerUrl: 'bar', - secretToken: 'bar', - checked: undefined, - }, - ]); - }); - it('selects policy elastic agent on cloud when available', () => { - const data: APIResponseType = { - agents: [policyElasticAgentOnCloud, ...agents], - cloudStandaloneSetup: undefined, - hasPolicyElasticOnCloud: true, - }; - const options = getEnvironmentConfigurationOptions({ - isCloudEnabled: true, - data, - }); - expect(options).toEqual([ - { - key: 'onPrem_standalone', - label: 'Default Standalone configuration', - apmServerUrl: 'http://localhost:8200', - secretToken: '', - checked: undefined, - }, - { - isGroupLabel: true, - key: 'fleet_policies', - label: 'Fleet policies', - }, - { - key: '3', - label: 'policy-elastic-agent-on-cloud', - apmServerUrl: 'baz', - secretToken: 'baz', - checked: 'on', - }, - { - key: '1', - label: 'agent foo', - apmServerUrl: 'foo', - secretToken: 'foo', - checked: undefined, - }, - { - key: '2', - label: 'agent bar', - apmServerUrl: 'bar', - secretToken: 'bar', - checked: undefined, - }, - ]); - }); - }); - }); - describe('Running on prem', () => { - it('shows apm on prem standalone option', () => { - const data: APIResponseType = { - agents: [], - cloudStandaloneSetup: undefined, - hasPolicyElasticOnCloud: false, - }; - const options = getEnvironmentConfigurationOptions({ - isCloudEnabled: false, - data, - }); - expect(options).toEqual([ - { - key: 'onPrem_standalone', - label: 'Default Standalone configuration', - apmServerUrl: 'http://localhost:8200', - secretToken: '', - checked: 'on', - }, - ]); - }); - it('shows apm on prem standalone option and fleet agents options', () => { - const data: APIResponseType = { - agents, - cloudStandaloneSetup: undefined, - hasPolicyElasticOnCloud: false, - }; - const options = getEnvironmentConfigurationOptions({ - isCloudEnabled: false, - data, - }); - expect(options).toEqual([ - { - key: 'onPrem_standalone', - label: 'Default Standalone configuration', - apmServerUrl: 'http://localhost:8200', - secretToken: '', - checked: 'on', - }, - { - isGroupLabel: true, - key: 'fleet_policies', - label: 'Fleet policies', - }, - { - key: '1', - label: 'agent foo', - apmServerUrl: 'foo', - secretToken: 'foo', - checked: undefined, - }, - { - key: '2', - label: 'agent bar', - apmServerUrl: 'bar', - secretToken: 'bar', - checked: undefined, - }, - ]); - }); - }); - }); -}); diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/index.tsx b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/index.tsx index 34719e3f0a712d..e5badb81928c2b 100644 --- a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/index.tsx @@ -17,20 +17,11 @@ import React, { useEffect, useMemo, useState } from 'react'; import styled from 'styled-components'; import { APIReturnType } from '../../../../services/rest/createCallApmApi'; import { CopyCommands } from '../copy_commands'; -import { - EnvironmentConfigurationOption, - EnvironmentConfigurationSelector, -} from './environment_configuration_selector'; +import { PolicySelectorOption, PolicySelector } from './policy_selector'; import { getCommands } from './commands/get_commands'; +import { getPolicyOptions } from './get_policy_options'; -const POLICY_ELASTIC_AGENT_ON_CLOUD = 'policy-elastic-agent-on-cloud'; - -interface Props { - variantId: string; - http: HttpStart; - basePath: string; - isCloudEnabled: boolean; -} +export type APIResponseType = APIReturnType<'GET /api/apm/fleet/agents'>; const CentralizedContainer = styled.div` display: flex; @@ -38,13 +29,6 @@ const CentralizedContainer = styled.div` align-items: center; `; -type APIResponseType = APIReturnType<'GET /api/apm/fleet/agents'>; - -const DEFAULT_STANDALONE_CONFIG_LABEL = i18n.translate( - 'xpack.apm.tutorial.agent_config.defaultStandaloneConfig', - { defaultMessage: 'Default Standalone configuration' } -); - const MANAGE_FLEET_POLICIES_LABEL = i18n.translate( 'xpack.apm.tutorial.agent_config.manageFleetPolicies', { defaultMessage: 'Manage fleet policies' } @@ -55,65 +39,11 @@ const GET_STARTED_WITH_FLEET_LABEL = i18n.translate( { defaultMessage: 'Get started with fleet' } ); -export function getEnvironmentConfigurationOptions({ - isCloudEnabled, - data, -}: { +interface Props { + variantId: string; + http: HttpStart; + basePath: string; isCloudEnabled: boolean; - data: APIResponseType; -}) { - const newOptions: EnvironmentConfigurationOption[] = []; - // When running on cloud and apm.url is defined - if (isCloudEnabled && data.cloudStandaloneSetup?.apmServerUrl) { - // pushes APM cloud standalone - newOptions.push({ - key: 'cloud_standalone', - label: DEFAULT_STANDALONE_CONFIG_LABEL, - apmServerUrl: data.cloudStandaloneSetup?.apmServerUrl, - secretToken: data.cloudStandaloneSetup?.secretToken, - checked: data.hasPolicyElasticOnCloud ? undefined : 'on', - }); - } else { - // pushes APM onprem standalone - newOptions.push({ - key: 'onPrem_standalone', - label: DEFAULT_STANDALONE_CONFIG_LABEL, - apmServerUrl: 'http://localhost:8200', - secretToken: '', - checked: data.hasPolicyElasticOnCloud ? undefined : 'on', - }); - } - - if (data.agents.length) { - // Adds fleet policies group label - newOptions.push({ - key: 'fleet_policies', - label: i18n.translate( - 'xpack.apm.tutorial.agent_config.fleetPoliciesLabel', - { defaultMessage: 'Fleet policies' } - ), - isGroupLabel: true, - }); - // remaining agents with APM integration - newOptions.push( - ...data.agents.map( - ({ - id, - name, - apmServerUrl, - secretToken, - }): EnvironmentConfigurationOption => ({ - key: id, - label: name, - apmServerUrl, - secretToken, - checked: name === POLICY_ELASTIC_AGENT_ON_CLOUD ? 'on' : undefined, - }) - ) - ); - } - - return newOptions; } function TutorialAgentSecretTokenSelector({ @@ -124,14 +54,10 @@ function TutorialAgentSecretTokenSelector({ }: Props) { const [data, setData] = useState({ agents: [], - hasPolicyElasticOnCloud: false, cloudStandaloneSetup: undefined, }); const [isLoading, setIsLoading] = useState(true); - const [ - selectedOption, - setSelectedOption, - ] = useState(); + const [selectedOption, setSelectedOption] = useState(); useEffect(() => { async function fetchData() { @@ -142,14 +68,19 @@ function TutorialAgentSecretTokenSelector({ } catch (e) { console.error('Error while fetching fleet agents.', e); } - setIsLoading(false); } fetchData(); }, [http]); // Depending the environment running (onPrem/Cloud) different values must be available and automatically selected const options = useMemo(() => { - return getEnvironmentConfigurationOptions({ isCloudEnabled, data }); + const { availableOptions, defaultSelectedOption } = getPolicyOptions({ + isCloudEnabled, + data, + }); + setSelectedOption(defaultSelectedOption); + setIsLoading(false); + return availableOptions; }, [data, isCloudEnabled]); if (isLoading) { @@ -162,7 +93,7 @@ function TutorialAgentSecretTokenSelector({ const commands = getCommands({ variantId, - environmentDetails: { + policyDetails: { apmServerUrl: selectedOption?.apmServerUrl, secretToken: selectedOption?.secretToken, }, @@ -183,7 +114,7 @@ function TutorialAgentSecretTokenSelector({ <> - diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/policy_selector.tsx b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/policy_selector.tsx new file mode 100644 index 00000000000000..54b84ad6926c4f --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/policy_selector.tsx @@ -0,0 +1,62 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + EuiComboBox, + EuiComboBoxOptionOption, + EuiFormRow, + EuiLink, + EuiText, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import React from 'react'; + +export type PolicySelectorOption = EuiComboBoxOptionOption & { + apmServerUrl?: string; + secretToken?: string; +}; + +interface Props { + options: PolicySelectorOption[]; + selectedOption?: PolicySelectorOption; + onChange: (selectedOption?: PolicySelectorOption) => void; + fleetLink: { + label: string; + href: string; + }; +} + +export function PolicySelector({ + options, + selectedOption, + onChange, + fleetLink, +}: Props) { + return ( + + {fleetLink.label} + + } + > + { + onChange(selectedOptions[0]); + }} + /> + + ); +} diff --git a/x-pack/plugins/apm/server/routes/fleet.ts b/x-pack/plugins/apm/server/routes/fleet.ts index 3e16228ef1b99b..3b3cf61c383e33 100644 --- a/x-pack/plugins/apm/server/routes/fleet.ts +++ b/x-pack/plugins/apm/server/routes/fleet.ts @@ -54,12 +54,7 @@ const fleetAgentsRoute = createApmServerRoute({ fleetPluginStart, }); - const hasPolicyElasticOnCloud = agents.some( - ({ name }) => name === POLICY_ELASTIC_AGENT_ON_CLOUD - ); - return { - hasPolicyElasticOnCloud, cloudStandaloneSetup, agents: agents.map((agent) => { const packagePolicy = policiesGroupedById[agent.id]; From 915754fe1f59c9a60c7a6d8d6e7108974f54fccc Mon Sep 17 00:00:00 2001 From: cauemarcondes Date: Tue, 22 Jun 2021 14:44:00 -0400 Subject: [PATCH 06/11] adding unit test --- .../tutorial/config_agent/index.test.tsx | 208 ++++++++++++++++++ .../shared/tutorial/config_agent/index.tsx | 8 +- .../tutorial/config_agent/policy_selector.tsx | 3 +- 3 files changed, 215 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/index.test.tsx b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/index.test.tsx index 1fec1c76430ebd..9947517d060248 100644 --- a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/index.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/index.test.tsx @@ -4,3 +4,211 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ +import { fireEvent, render, screen } from '@testing-library/react'; +import { HttpStart } from 'kibana/public'; +import React from 'react'; +import TutorialAgentSecretTokenSelector from './'; + +const policyElasticAgentOnCloudAgent = { + id: 'policy-elastic-agent-on-cloud', + name: 'Elastic Cloud agent policy', + apmServerUrl: 'apm_cloud_url', + secretToken: 'apm_cloud_token', +}; + +const agents = [ + { + id: '1', + name: 'agent foo', + apmServerUrl: 'foo', + secretToken: 'foo', + }, + { + id: '2', + name: 'agent bar', + apmServerUrl: 'bar', + secretToken: 'bar', + }, +]; + +describe('TutorialAgentSecretTokenSelector', () => { + beforeAll(() => { + jest.spyOn(console, 'error').mockImplementation(() => null); + }); + + afterAll(() => { + jest.restoreAllMocks(); + }); + it('renders loading component while API is being called', () => { + const component = render( + + ); + expect(component.getByTestId('loading')).toBeInTheDocument(); + }); + it('updates commands when a different policy is selected', async () => { + const component = render( + + ); + expect( + await screen.findByText('Default Standalone configuration') + ).toBeInTheDocument(); + let commands = component.getByTestId('commands').innerHTML; + expect(commands).not.toEqual(''); + expect(commands).toMatchInlineSnapshot(` + "java -javaagent:/path/to/elastic-apm-agent-<version>.jar \\\\ + -Delastic.apm.service_name=my-application \\\\ + -Delastic.apm.server_urls=http://localhost:8200 \\\\ + -Delastic.apm.secret_token= \\\\ + -Delastic.apm.environment=production \\\\ + -Delastic.apm.application_packages=org.example \\\\ + -jar my-application.jar" + `); + + fireEvent.click(component.getByTestId('comboBoxToggleListButton')); + fireEvent.click(component.getByText('agent foo')); + commands = component.getByTestId('commands').innerHTML; + expect(commands).not.toEqual(''); + expect(commands).toMatchInlineSnapshot(` + "java -javaagent:/path/to/elastic-apm-agent-<version>.jar \\\\ + -Delastic.apm.service_name=my-application \\\\ + -Delastic.apm.server_urls=foo \\\\ + -Delastic.apm.secret_token=foo \\\\ + -Delastic.apm.environment=production \\\\ + -Delastic.apm.application_packages=org.example \\\\ + -jar my-application.jar" + `); + }); + describe('running on prem', () => { + it('selects defaul standalone by defauls', async () => { + const component = render( + + ); + expect( + await screen.findByText('Default Standalone configuration') + ).toBeInTheDocument(); + expect( + component.getByTestId('policySelector_onPrem_standalone') + ).toBeInTheDocument(); + const commands = component.getByTestId('commands').innerHTML; + expect(commands).not.toEqual(''); + expect(commands).toMatchInlineSnapshot(` + "java -javaagent:/path/to/elastic-apm-agent-<version>.jar \\\\ + -Delastic.apm.service_name=my-application \\\\ + -Delastic.apm.server_urls=http://localhost:8200 \\\\ + -Delastic.apm.secret_token= \\\\ + -Delastic.apm.environment=production \\\\ + -Delastic.apm.application_packages=org.example \\\\ + -jar my-application.jar" + `); + }); + }); + describe('running on cloud', () => { + it('selects defaul standalone by defauls', async () => { + const component = render( + + ); + expect( + await screen.findByText('Default Standalone configuration') + ).toBeInTheDocument(); + expect( + component.getByTestId('policySelector_cloud_standalone') + ).toBeInTheDocument(); + const commands = component.getByTestId('commands').innerHTML; + expect(commands).not.toEqual(''); + expect(commands).toMatchInlineSnapshot(` + "java -javaagent:/path/to/elastic-apm-agent-<version>.jar \\\\ + -Delastic.apm.service_name=my-application \\\\ + -Delastic.apm.server_urls=cloud_url \\\\ + -Delastic.apm.secret_token=cloud_token \\\\ + -Delastic.apm.environment=production \\\\ + -Delastic.apm.application_packages=org.example \\\\ + -jar my-application.jar" + `); + }); + it('selects policy elastic agent on cloud when available by default', async () => { + const component = render( + + ); + expect( + await screen.findByText('Elastic Cloud agent policy') + ).toBeInTheDocument(); + expect( + component.getByTestId('policySelector_policy-elastic-agent-on-cloud') + ).toBeInTheDocument(); + const commands = component.getByTestId('commands').innerHTML; + expect(commands).not.toEqual(''); + expect(commands).toMatchInlineSnapshot(` + "java -javaagent:/path/to/elastic-apm-agent-<version>.jar \\\\ + -Delastic.apm.service_name=my-application \\\\ + -Delastic.apm.server_urls=apm_cloud_url \\\\ + -Delastic.apm.secret_token=apm_cloud_token \\\\ + -Delastic.apm.environment=production \\\\ + -Delastic.apm.application_packages=org.example \\\\ + -jar my-application.jar" + `); + }); + }); +}); diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/index.tsx b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/index.tsx index e5badb81928c2b..06939decdf53ab 100644 --- a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/index.tsx @@ -64,7 +64,9 @@ function TutorialAgentSecretTokenSelector({ setIsLoading(true); try { const response = await http.get('/api/apm/fleet/agents'); - setData(response as APIResponseType); + if (response) { + setData(response as APIResponseType); + } } catch (e) { console.error('Error while fetching fleet agents.', e); } @@ -85,7 +87,7 @@ function TutorialAgentSecretTokenSelector({ if (isLoading) { return ( - + ); @@ -107,7 +109,7 @@ function TutorialAgentSecretTokenSelector({ } : { label: GET_STARTED_WITH_FLEET_LABEL, - href: `${basePath}/app/fleet#/integrations/detail/apm-0.2.0/overview`, + href: `${basePath}/app/integrations#/detail/apm-0.2.0/overview`, }; return ( diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/policy_selector.tsx b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/policy_selector.tsx index 54b84ad6926c4f..ae337cd7902a9e 100644 --- a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/policy_selector.tsx +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/policy_selector.tsx @@ -40,7 +40,7 @@ export function PolicySelector({ @@ -49,6 +49,7 @@ export function PolicySelector({ } > Date: Tue, 22 Jun 2021 15:57:58 -0400 Subject: [PATCH 07/11] fixing TS issue --- x-pack/plugins/fleet/server/mocks/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/plugins/fleet/server/mocks/index.ts b/x-pack/plugins/fleet/server/mocks/index.ts index a94f274b202adf..1e2a0bc7649f05 100644 --- a/x-pack/plugins/fleet/server/mocks/index.ts +++ b/x-pack/plugins/fleet/server/mocks/index.ts @@ -76,6 +76,7 @@ export const createMockAgentPolicyService = (): jest.Mocked Date: Tue, 22 Jun 2021 16:23:31 -0400 Subject: [PATCH 08/11] adding help text --- .../shared/tutorial/config_agent/policy_selector.tsx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/policy_selector.tsx b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/policy_selector.tsx index ae337cd7902a9e..e90ed30fa01dd2 100644 --- a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/policy_selector.tsx +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/policy_selector.tsx @@ -47,6 +47,13 @@ export function PolicySelector({ {fleetLink.label} } + helpText={i18n.translate( + 'xpack.apm.tutorial.agent_config.choosePolicy.helper', + { + defaultMessage: + 'Adds the selected policy configuration to the snippet below.', + } + )} > Date: Tue, 22 Jun 2021 16:28:40 -0400 Subject: [PATCH 09/11] renaming --- .../shared/tutorial/config_agent/index.test.tsx | 14 +++++++------- .../shared/tutorial/config_agent/index.tsx | 4 ++-- .../shared/tutorial/config_agent/rum_script.tsx | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/index.test.tsx b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/index.test.tsx index 9947517d060248..0c0f01ad80e4b3 100644 --- a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/index.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/index.test.tsx @@ -7,7 +7,7 @@ import { fireEvent, render, screen } from '@testing-library/react'; import { HttpStart } from 'kibana/public'; import React from 'react'; -import TutorialAgentSecretTokenSelector from './'; +import TutorialConfigAgent from './'; const policyElasticAgentOnCloudAgent = { id: 'policy-elastic-agent-on-cloud', @@ -31,7 +31,7 @@ const agents = [ }, ]; -describe('TutorialAgentSecretTokenSelector', () => { +describe('TutorialConfigAgent', () => { beforeAll(() => { jest.spyOn(console, 'error').mockImplementation(() => null); }); @@ -41,7 +41,7 @@ describe('TutorialAgentSecretTokenSelector', () => { }); it('renders loading component while API is being called', () => { const component = render( - { }); it('updates commands when a different policy is selected', async () => { const component = render( - { describe('running on prem', () => { it('selects defaul standalone by defauls', async () => { const component = render( - { describe('running on cloud', () => { it('selects defaul standalone by defauls', async () => { const component = render( - { }); it('selects policy elastic agent on cloud when available by default', async () => { const component = render( - Date: Wed, 23 Jun 2021 11:11:03 -0400 Subject: [PATCH 10/11] moving files --- x-pack/plugins/apm/public/plugin.ts | 4 ++-- .../shared => }/tutorial/config_agent/commands/django.ts | 0 .../shared => }/tutorial/config_agent/commands/dotnet.ts | 2 -- .../shared => }/tutorial/config_agent/commands/flask.ts | 0 .../tutorial/config_agent/commands/get_commands.test.ts | 0 .../tutorial/config_agent/commands/get_commands.ts | 0 .../shared => }/tutorial/config_agent/commands/go.ts | 0 .../shared => }/tutorial/config_agent/commands/java.ts | 0 .../shared => }/tutorial/config_agent/commands/node.ts | 0 .../shared => }/tutorial/config_agent/commands/php.ts | 0 .../shared => }/tutorial/config_agent/commands/rack.ts | 0 .../shared => }/tutorial/config_agent/commands/rails.ts | 1 - .../shared => }/tutorial/config_agent/commands/rum.ts | 4 +--- .../tutorial => tutorial/config_agent}/copy_commands.tsx | 0 .../tutorial/config_agent/get_policy_options.test.ts | 2 +- .../shared => }/tutorial/config_agent/get_policy_options.ts | 0 .../shared => }/tutorial/config_agent/index.test.tsx | 0 .../{components/shared => }/tutorial/config_agent/index.tsx | 5 +++-- .../shared => }/tutorial/config_agent/policy_selector.tsx | 1 + .../shared => }/tutorial/config_agent/rum_script.tsx | 0 20 files changed, 8 insertions(+), 11 deletions(-) rename x-pack/plugins/apm/public/{components/shared => }/tutorial/config_agent/commands/django.ts (100%) rename x-pack/plugins/apm/public/{components/shared => }/tutorial/config_agent/commands/dotnet.ts (91%) rename x-pack/plugins/apm/public/{components/shared => }/tutorial/config_agent/commands/flask.ts (100%) rename x-pack/plugins/apm/public/{components/shared => }/tutorial/config_agent/commands/get_commands.test.ts (100%) rename x-pack/plugins/apm/public/{components/shared => }/tutorial/config_agent/commands/get_commands.ts (100%) rename x-pack/plugins/apm/public/{components/shared => }/tutorial/config_agent/commands/go.ts (100%) rename x-pack/plugins/apm/public/{components/shared => }/tutorial/config_agent/commands/java.ts (100%) rename x-pack/plugins/apm/public/{components/shared => }/tutorial/config_agent/commands/node.ts (100%) rename x-pack/plugins/apm/public/{components/shared => }/tutorial/config_agent/commands/php.ts (100%) rename x-pack/plugins/apm/public/{components/shared => }/tutorial/config_agent/commands/rack.ts (100%) rename x-pack/plugins/apm/public/{components/shared => }/tutorial/config_agent/commands/rails.ts (92%) rename x-pack/plugins/apm/public/{components/shared => }/tutorial/config_agent/commands/rum.ts (94%) rename x-pack/plugins/apm/public/{components/shared/tutorial => tutorial/config_agent}/copy_commands.tsx (100%) rename x-pack/plugins/apm/public/{components/shared => }/tutorial/config_agent/get_policy_options.test.ts (99%) rename x-pack/plugins/apm/public/{components/shared => }/tutorial/config_agent/get_policy_options.ts (100%) rename x-pack/plugins/apm/public/{components/shared => }/tutorial/config_agent/index.test.tsx (100%) rename x-pack/plugins/apm/public/{components/shared => }/tutorial/config_agent/index.tsx (95%) rename x-pack/plugins/apm/public/{components/shared => }/tutorial/config_agent/policy_selector.tsx (96%) rename x-pack/plugins/apm/public/{components/shared => }/tutorial/config_agent/rum_script.tsx (100%) diff --git a/x-pack/plugins/apm/public/plugin.ts b/x-pack/plugins/apm/public/plugin.ts index 9f8c7ada96e381..0f0d0727990612 100644 --- a/x-pack/plugins/apm/public/plugin.ts +++ b/x-pack/plugins/apm/public/plugin.ts @@ -177,12 +177,12 @@ export class ApmPlugin implements Plugin { pluginSetupDeps.home?.tutorials.registerCustomComponent( 'TutorialConfigAgent', - () => import('./components/shared/tutorial/config_agent') + () => import('./tutorial/config_agent') ); pluginSetupDeps.home?.tutorials.registerCustomComponent( 'TutorialConfigAgentRumScript', - () => import('./components/shared/tutorial/config_agent/rum_script') + () => import('./tutorial/config_agent/rum_script') ); plugins.observability.dashboard.register({ diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/django.ts b/x-pack/plugins/apm/public/tutorial/config_agent/commands/django.ts similarity index 100% rename from x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/django.ts rename to x-pack/plugins/apm/public/tutorial/config_agent/commands/django.ts diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/dotnet.ts b/x-pack/plugins/apm/public/tutorial/config_agent/commands/dotnet.ts similarity index 91% rename from x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/dotnet.ts rename to x-pack/plugins/apm/public/tutorial/config_agent/commands/dotnet.ts index 0ed7a874a95aea..e083a2b45c716d 100644 --- a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/dotnet.ts +++ b/x-pack/plugins/apm/public/tutorial/config_agent/commands/dotnet.ts @@ -4,8 +4,6 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -// TODO: ${'http://localhost:8200'}' fallback server_url - export const dotnet = `{ "ElasticApm": { "SecretToken": "{{{secretToken}}}", diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/flask.ts b/x-pack/plugins/apm/public/tutorial/config_agent/commands/flask.ts similarity index 100% rename from x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/flask.ts rename to x-pack/plugins/apm/public/tutorial/config_agent/commands/flask.ts diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/get_commands.test.ts b/x-pack/plugins/apm/public/tutorial/config_agent/commands/get_commands.test.ts similarity index 100% rename from x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/get_commands.test.ts rename to x-pack/plugins/apm/public/tutorial/config_agent/commands/get_commands.test.ts diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/get_commands.ts b/x-pack/plugins/apm/public/tutorial/config_agent/commands/get_commands.ts similarity index 100% rename from x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/get_commands.ts rename to x-pack/plugins/apm/public/tutorial/config_agent/commands/get_commands.ts diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/go.ts b/x-pack/plugins/apm/public/tutorial/config_agent/commands/go.ts similarity index 100% rename from x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/go.ts rename to x-pack/plugins/apm/public/tutorial/config_agent/commands/go.ts diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/java.ts b/x-pack/plugins/apm/public/tutorial/config_agent/commands/java.ts similarity index 100% rename from x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/java.ts rename to x-pack/plugins/apm/public/tutorial/config_agent/commands/java.ts diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/node.ts b/x-pack/plugins/apm/public/tutorial/config_agent/commands/node.ts similarity index 100% rename from x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/node.ts rename to x-pack/plugins/apm/public/tutorial/config_agent/commands/node.ts diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/php.ts b/x-pack/plugins/apm/public/tutorial/config_agent/commands/php.ts similarity index 100% rename from x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/php.ts rename to x-pack/plugins/apm/public/tutorial/config_agent/commands/php.ts diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/rack.ts b/x-pack/plugins/apm/public/tutorial/config_agent/commands/rack.ts similarity index 100% rename from x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/rack.ts rename to x-pack/plugins/apm/public/tutorial/config_agent/commands/rack.ts diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/rails.ts b/x-pack/plugins/apm/public/tutorial/config_agent/commands/rails.ts similarity index 92% rename from x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/rails.ts rename to x-pack/plugins/apm/public/tutorial/config_agent/commands/rails.ts index faf816c6b5bb71..0f8a5508e1cebb 100644 --- a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/rails.ts +++ b/x-pack/plugins/apm/public/tutorial/config_agent/commands/rails.ts @@ -5,7 +5,6 @@ * 2.0. */ -// TODO: ${'http://localhost:8200'}' fallback server_url export const rails = `# config/elastic_apm.yml: # Set the service name - allowed characters: a-z, A-Z, 0-9, -, _ and space diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/rum.ts b/x-pack/plugins/apm/public/tutorial/config_agent/commands/rum.ts similarity index 94% rename from x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/rum.ts rename to x-pack/plugins/apm/public/tutorial/config_agent/commands/rum.ts index 96e5ed6b082655..f5de61f64c63ac 100644 --- a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/commands/rum.ts +++ b/x-pack/plugins/apm/public/tutorial/config_agent/commands/rum.ts @@ -7,7 +7,6 @@ import { i18n } from '@kbn/i18n'; -// TODO: doesn't have token export const rum = `import { init as initApm } from '@elastic/apm-rum' var apm = initApm({ @@ -48,13 +47,12 @@ var apm = initApm({ environment: 'production' })`; -// TODO: doesn't have token/url export const rumScript = `\ `; diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/copy_commands.tsx b/x-pack/plugins/apm/public/tutorial/config_agent/copy_commands.tsx similarity index 100% rename from x-pack/plugins/apm/public/components/shared/tutorial/copy_commands.tsx rename to x-pack/plugins/apm/public/tutorial/config_agent/copy_commands.tsx diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/get_policy_options.test.ts b/x-pack/plugins/apm/public/tutorial/config_agent/get_policy_options.test.ts similarity index 99% rename from x-pack/plugins/apm/public/components/shared/tutorial/config_agent/get_policy_options.test.ts rename to x-pack/plugins/apm/public/tutorial/config_agent/get_policy_options.test.ts index df5583d85b3f26..8a0a9702686563 100644 --- a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/get_policy_options.test.ts +++ b/x-pack/plugins/apm/public/tutorial/config_agent/get_policy_options.test.ts @@ -5,7 +5,7 @@ * 2.0. */ import { getPolicyOptions } from './get_policy_options'; -import { APIReturnType } from '../../../../services/rest/createCallApmApi'; +import { APIReturnType } from '../../services/rest/createCallApmApi'; type APIResponseType = APIReturnType<'GET /api/apm/fleet/agents'>; diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/get_policy_options.ts b/x-pack/plugins/apm/public/tutorial/config_agent/get_policy_options.ts similarity index 100% rename from x-pack/plugins/apm/public/components/shared/tutorial/config_agent/get_policy_options.ts rename to x-pack/plugins/apm/public/tutorial/config_agent/get_policy_options.ts diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/index.test.tsx b/x-pack/plugins/apm/public/tutorial/config_agent/index.test.tsx similarity index 100% rename from x-pack/plugins/apm/public/components/shared/tutorial/config_agent/index.test.tsx rename to x-pack/plugins/apm/public/tutorial/config_agent/index.test.tsx diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/index.tsx b/x-pack/plugins/apm/public/tutorial/config_agent/index.tsx similarity index 95% rename from x-pack/plugins/apm/public/components/shared/tutorial/config_agent/index.tsx rename to x-pack/plugins/apm/public/tutorial/config_agent/index.tsx index 6739cf2684971a..56d79d00790950 100644 --- a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/index.tsx +++ b/x-pack/plugins/apm/public/tutorial/config_agent/index.tsx @@ -15,8 +15,8 @@ import { i18n } from '@kbn/i18n'; import { HttpStart } from 'kibana/public'; import React, { useEffect, useMemo, useState } from 'react'; import styled from 'styled-components'; -import { APIReturnType } from '../../../../services/rest/createCallApmApi'; -import { CopyCommands } from '../copy_commands'; +import { APIReturnType } from '../..//services/rest/createCallApmApi'; +import { CopyCommands } from './copy_commands'; import { PolicySelectorOption, PolicySelector } from './policy_selector'; import { getCommands } from './commands/get_commands'; import { getPolicyOptions } from './get_policy_options'; @@ -58,6 +58,7 @@ function TutorialConfigAgent({ }); const [isLoading, setIsLoading] = useState(true); const [selectedOption, setSelectedOption] = useState(); + console.log('### caue ~ selectedOption', selectedOption); useEffect(() => { async function fetchData() { diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/policy_selector.tsx b/x-pack/plugins/apm/public/tutorial/config_agent/policy_selector.tsx similarity index 96% rename from x-pack/plugins/apm/public/components/shared/tutorial/config_agent/policy_selector.tsx rename to x-pack/plugins/apm/public/tutorial/config_agent/policy_selector.tsx index e90ed30fa01dd2..4c76c822ab3ac1 100644 --- a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/policy_selector.tsx +++ b/x-pack/plugins/apm/public/tutorial/config_agent/policy_selector.tsx @@ -62,6 +62,7 @@ export function PolicySelector({ options={options} selectedOptions={selectedOption ? [selectedOption] : []} onChange={(selectedOptions) => { + console.log('### caue ~ selectedOptions', selectedOptions); onChange(selectedOptions[0]); }} /> diff --git a/x-pack/plugins/apm/public/components/shared/tutorial/config_agent/rum_script.tsx b/x-pack/plugins/apm/public/tutorial/config_agent/rum_script.tsx similarity index 100% rename from x-pack/plugins/apm/public/components/shared/tutorial/config_agent/rum_script.tsx rename to x-pack/plugins/apm/public/tutorial/config_agent/rum_script.tsx From 05eb303451a2883a763bf37683a5b46b4f058eea Mon Sep 17 00:00:00 2001 From: cauemarcondes Date: Wed, 23 Jun 2021 11:11:59 -0400 Subject: [PATCH 11/11] updating apm int version --- x-pack/plugins/apm/public/tutorial/config_agent/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/apm/public/tutorial/config_agent/index.tsx b/x-pack/plugins/apm/public/tutorial/config_agent/index.tsx index 56d79d00790950..48220f59418a11 100644 --- a/x-pack/plugins/apm/public/tutorial/config_agent/index.tsx +++ b/x-pack/plugins/apm/public/tutorial/config_agent/index.tsx @@ -110,7 +110,7 @@ function TutorialConfigAgent({ } : { label: GET_STARTED_WITH_FLEET_LABEL, - href: `${basePath}/app/integrations#/detail/apm-0.2.0/overview`, + href: `${basePath}/app/integrations#/detail/apm-0.3.0/overview`, }; return (