diff --git a/x-pack/plugins/observability_onboarding/public/components/app/custom_logs/wizard/install_elastic_agent.tsx b/x-pack/plugins/observability_onboarding/public/components/app/custom_logs/wizard/install_elastic_agent.tsx
index a7ed59422d7cd..0dfefc6130522 100644
--- a/x-pack/plugins/observability_onboarding/public/components/app/custom_logs/wizard/install_elastic_agent.tsx
+++ b/x-pack/plugins/observability_onboarding/public/components/app/custom_logs/wizard/install_elastic_agent.tsx
@@ -15,6 +15,7 @@ import {
EuiButtonGroup,
EuiCodeBlock,
EuiSteps,
+ EuiSkeletonRectangle,
} from '@elastic/eui';
import {
StepPanel,
@@ -22,9 +23,7 @@ import {
StepPanelFooter,
} from '../../../shared/step_panel';
import { useWizard } from '.';
-import { useFetcher } from '../../../../hooks/use_fetcher';
-// import { useKibana } from '@kbn/kibana-react-plugin/public';
-// import type { CloudSetup } from '@kbn/cloud-plugin/public';
+import { FETCH_STATUS, useFetcher } from '../../../../hooks/use_fetcher';
type ElasticAgentPlatform = 'linux-tar' | 'macos' | 'windows';
export function InstallElasticAgent() {
@@ -41,48 +40,47 @@ export function InstallElasticAgent() {
goBack();
}
- const { data: installShipperSetup } = useFetcher((callApi) => {
- if (CurrentStep !== InstallElasticAgent) {
- return;
- }
- return callApi(
- 'POST /internal/observability_onboarding/custom_logs/install_shipper_setup',
- {
- params: {
- body: {
- name: wizardState.datasetName,
- state: {
- datasetName: wizardState.datasetName,
- customConfigurations: wizardState.customConfigurations,
- logFilePaths: wizardState.logFilePaths,
+ const { data: installShipperSetup, status: installShipperSetupStatus } =
+ useFetcher((callApi) => {
+ if (CurrentStep !== InstallElasticAgent) {
+ return;
+ }
+
+ return callApi(
+ 'POST /internal/observability_onboarding/custom_logs/install_shipper_setup',
+ {
+ params: {
+ body: {
+ name: wizardState.datasetName,
+ state: {
+ datasetName: wizardState.datasetName,
+ namespace: wizardState.namespace,
+ customConfigurations: wizardState.customConfigurations,
+ logFilePaths: wizardState.logFilePaths,
+ },
},
},
- },
+ }
+ );
+ }, []);
+
+ const { data: yamlConfig = '', status: yamlConfigStatus } = useFetcher(
+ (callApi) => {
+ if (installShipperSetup?.apiKeyId) {
+ return callApi(
+ 'GET /api/observability_onboarding/elastic_agent/config',
+ {
+ headers: {
+ authorization: `ApiKey ${installShipperSetup?.apiKeyEncoded}`,
+ },
+ }
+ );
}
- );
- }, []);
+ },
+ [installShipperSetup?.apiKeyId, installShipperSetup?.apiKeyEncoded]
+ );
const apiKeyEncoded = installShipperSetup?.apiKeyEncoded;
- const esHost = installShipperSetup?.esHost;
-
- const elasticAgentYaml = getElasticAgentYaml({
- esHost,
- apiKeyEncoded,
- logfileId: 'custom-logs-abcdefgh',
- logfileNamespace: 'default',
- logfileStreams: [
- ...wizardState.logFilePaths.map((path) => ({
- id: `logs-onboarding-${wizardState.datasetName}`,
- dataset: wizardState.datasetName,
- path,
- })),
- // {
- // id: 'logs-onboarding-demo-app',
- // dataset: 'demo1',
- // path: '/home/oliver/github/logs-onboarding-demo-app/combined.log',
- // },
- ],
- });
return (
@@ -101,7 +99,10 @@ export function InstallElasticAgent() {
steps={[
{
title: 'Install the Elastic Agent',
- status: 'current',
+ status:
+ installShipperSetupStatus === FETCH_STATUS.LOADING
+ ? 'loading'
+ : 'current',
children: (
<>
@@ -128,20 +129,34 @@ export function InstallElasticAgent() {
}
/>
-
- {getInstallShipperCommand({
- elasticAgentPlatform,
- apiKeyEncoded,
- apiEndpoint: installShipperSetup?.apiEndpoint,
- scriptDownloadUrl: installShipperSetup?.scriptDownloadUrl,
- })}
-
+
+
+ {getInstallShipperCommand({
+ elasticAgentPlatform,
+ apiKeyEncoded,
+ apiEndpoint: installShipperSetup?.apiEndpoint,
+ scriptDownloadUrl:
+ installShipperSetup?.scriptDownloadUrl,
+ })}
+
+
>
),
},
{
title: 'Configure the agent',
- status: 'incomplete',
+ status:
+ yamlConfigStatus === FETCH_STATUS.LOADING
+ ? 'loading'
+ : 'incomplete',
children: (
<>
@@ -151,15 +166,23 @@ export function InstallElasticAgent() {
-
- {elasticAgentYaml}
-
+
+
+ {yamlConfig}
+
+
;
-}) {
- const apiKeyBeats = Buffer.from(apiKeyEncoded, 'base64').toString('utf8');
- return `
-outputs:
- default:
- type: elasticsearch
- hosts:
- - '${esHost}'
- api_key: ${apiKeyBeats}
-
-inputs:
- - id: ${logfileId}
- type: logfile
- data_stream:
- namespace: ${logfileNamespace}
- streams:
-${logfileStreams
- .map(
- ({ id, dataset, path }) => ` - id: ${id}
- data_stream:
- dataset: ${dataset}
- paths:
- - ${path}`
- )
- .join('\n')}`.trim();
-}
diff --git a/x-pack/plugins/observability_onboarding/server/routes/custom_logs/route.ts b/x-pack/plugins/observability_onboarding/server/routes/custom_logs/route.ts
index 87a83bb6d5fe4..d6b2cf0ff13ea 100644
--- a/x-pack/plugins/observability_onboarding/server/routes/custom_logs/route.ts
+++ b/x-pack/plugins/observability_onboarding/server/routes/custom_logs/route.ts
@@ -68,11 +68,13 @@ const createApiKeyRoute = createObservabilityOnboardingServerRoute({
});
const savedObjectsClient = coreStart.savedObjects.getScopedClient(request);
- saveObservabilityOnboardingState({
+
+ await saveObservabilityOnboardingState({
savedObjectsClient,
apiKeyId,
observabilityOnboardingState: { state } as ObservabilityOnboardingState,
});
+
return {
apiKeyId, // key the status off this
apiKeyEncoded,
diff --git a/x-pack/plugins/observability_onboarding/server/routes/elastic_agent/generate_yml.ts b/x-pack/plugins/observability_onboarding/server/routes/elastic_agent/generate_yml.ts
new file mode 100644
index 0000000000000..fb27500639fc1
--- /dev/null
+++ b/x-pack/plugins/observability_onboarding/server/routes/elastic_agent/generate_yml.ts
@@ -0,0 +1,59 @@
+/*
+ * 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 { dump, load } from 'js-yaml';
+
+export const generateYml = ({
+ datasetName = '',
+ namespace = '',
+ customConfigurations,
+ logFilePaths = [],
+ apiKey,
+ esHost,
+ logfileId,
+}: {
+ datasetName?: string;
+ namespace?: string;
+ customConfigurations?: string;
+ logFilePaths?: string[];
+ apiKey: string;
+ esHost: string[];
+ logfileId: string;
+}) => {
+ const customConfigYaml = load(customConfigurations ?? '');
+
+ return dump({
+ ...{
+ outputs: {
+ default: {
+ type: 'elasticsearch',
+ hosts: esHost,
+ api_key: apiKey,
+ },
+ },
+ inputs: [
+ {
+ id: logfileId,
+ type: 'logfile',
+ data_stream: {
+ namespace,
+ },
+ streams: [
+ {
+ id: `logs-onboarding-${datasetName}`,
+ data_stream: {
+ dataset: datasetName,
+ },
+ paths: logFilePaths,
+ },
+ ],
+ },
+ ],
+ },
+ ...customConfigYaml,
+ });
+};
diff --git a/x-pack/plugins/observability_onboarding/server/routes/elastic_agent/route.ts b/x-pack/plugins/observability_onboarding/server/routes/elastic_agent/route.ts
new file mode 100644
index 0000000000000..da71ec1f7f3c5
--- /dev/null
+++ b/x-pack/plugins/observability_onboarding/server/routes/elastic_agent/route.ts
@@ -0,0 +1,66 @@
+/*
+ * 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 type { Client } from '@elastic/elasticsearch';
+import { KibanaRequest } from '@kbn/core-http-server';
+import { HTTPAuthorizationHeader } from '@kbn/security-plugin/server';
+import { createObservabilityOnboardingServerRoute } from '../create_observability_onboarding_server_route';
+import { findLatestObservabilityOnboardingState } from '../custom_logs/find_latest_observability_onboarding_state';
+import { getESHosts } from '../custom_logs/get_es_hosts';
+import { generateYml } from './generate_yml';
+
+const getAuthenticationAPIKey = (request: KibanaRequest) => {
+ const authorizationHeader = HTTPAuthorizationHeader.parseFromRequest(request);
+ if (authorizationHeader && authorizationHeader.credentials) {
+ const apiKey = Buffer.from(authorizationHeader.credentials, 'base64')
+ .toString()
+ .split(':');
+ return {
+ apiKeyId: apiKey[0],
+ apiKey: apiKey[1],
+ };
+ }
+ throw new Error('Authorization header is missing');
+};
+
+const generateConfig = createObservabilityOnboardingServerRoute({
+ endpoint: 'GET /api/observability_onboarding/elastic_agent/config',
+ options: { tags: [] },
+ async handler(resources): Promise {
+ const { core, plugins, request } = resources;
+ const { apiKeyId, apiKey } = getAuthenticationAPIKey(request);
+
+ const coreStart = await core.start();
+ const savedObjectsClient =
+ coreStart.savedObjects.createInternalRepository();
+
+ const esHost = getESHosts({
+ cloudSetup: plugins.cloud.setup,
+ esClient: coreStart.elasticsearch.client.asInternalUser as Client,
+ });
+
+ const savedState = await findLatestObservabilityOnboardingState({
+ savedObjectsClient,
+ });
+
+ const yaml = generateYml({
+ datasetName: savedState?.state.datasetName,
+ customConfigurations: savedState?.state.customConfigurations,
+ logFilePaths: savedState?.state.logFilePaths,
+ namespace: savedState?.state.namespace,
+ apiKey: `${apiKeyId}:${apiKey}`,
+ esHost,
+ logfileId: `custom-logs-${Date.now()}`,
+ });
+
+ return yaml;
+ },
+});
+
+export const elasticAgentRouteRepository = {
+ ...generateConfig,
+};
diff --git a/x-pack/plugins/observability_onboarding/server/routes/index.ts b/x-pack/plugins/observability_onboarding/server/routes/index.ts
index e68bc3e075993..4833f44a2936c 100644
--- a/x-pack/plugins/observability_onboarding/server/routes/index.ts
+++ b/x-pack/plugins/observability_onboarding/server/routes/index.ts
@@ -10,11 +10,13 @@ import type {
} from '@kbn/server-route-repository';
import { statusRouteRepository } from './status/route';
import { customLogsRouteRepository } from './custom_logs/route';
+import { elasticAgentRouteRepository } from './elastic_agent/route';
function getTypedObservabilityOnboardingServerRouteRepository() {
const repository = {
...statusRouteRepository,
...customLogsRouteRepository,
+ ...elasticAgentRouteRepository,
};
return repository;
diff --git a/x-pack/plugins/observability_onboarding/server/saved_objects/observability_onboarding_status.ts b/x-pack/plugins/observability_onboarding/server/saved_objects/observability_onboarding_status.ts
index 7fa558dc20df3..40267f2318625 100644
--- a/x-pack/plugins/observability_onboarding/server/saved_objects/observability_onboarding_status.ts
+++ b/x-pack/plugins/observability_onboarding/server/saved_objects/observability_onboarding_status.ts
@@ -14,7 +14,8 @@ export interface ObservabilityOnboardingState {
state: {
datasetName: string;
customConfigurations: string;
- logFilePaths: string;
+ logFilePaths: string[];
+ namespace: string;
progress: Record;
};
}