Skip to content

Commit

Permalink
[Logs onboarding] elastic-agent.yml file now includes es host with po…
Browse files Browse the repository at this point in the history
…rts (elastic#162490)

Closes elastic#162141.

### Changes
- Created an `esLegacyConfigService` to access esConfiguration and get
the hosts (protocol + url + port).
- Initialised the service mentioned using
`core.elasticsearch.legacy.config$`.
- Injected `esLegacyConfigService` as a resource for routes.
- Stop service whenever plugin is stopped.
  • Loading branch information
yngrdyn committed Jul 26, 2023
1 parent de0d7b5 commit 7c16dd9
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 31 deletions.
11 changes: 10 additions & 1 deletion x-pack/plugins/observability_onboarding/server/plugin.ts
Expand Up @@ -24,6 +24,7 @@ import {
} from './types';
import { ObservabilityOnboardingConfig } from '.';
import { observabilityOnboardingState } from './saved_objects/observability_onboarding_status';
import { EsLegacyConfigService } from './services/es_legacy_config_service';

export class ObservabilityOnboardingPlugin
implements
Expand All @@ -35,6 +36,8 @@ export class ObservabilityOnboardingPlugin
>
{
private readonly logger: Logger;
esLegacyConfigService = new EsLegacyConfigService();

constructor(
private readonly initContext: PluginInitializerContext<ObservabilityOnboardingConfig>
) {
Expand All @@ -47,6 +50,7 @@ export class ObservabilityOnboardingPlugin
plugins: ObservabilityOnboardingPluginSetupDependencies
) {
this.logger.debug('observability_onboarding: Setup');
this.esLegacyConfigService.setup(core.elasticsearch.legacy.config$);

core.savedObjects.registerType(observabilityOnboardingState);

Expand All @@ -70,6 +74,9 @@ export class ObservabilityOnboardingPlugin
repository: getObservabilityOnboardingServerRouteRepository(),
plugins: resourcePlugins,
config,
services: {
esLegacyConfigService: this.esLegacyConfigService,
},
});

return {};
Expand All @@ -81,5 +88,7 @@ export class ObservabilityOnboardingPlugin
return {};
}

public stop() {}
public stop() {
this.esLegacyConfigService.stop();
}
}
Expand Up @@ -5,35 +5,22 @@
* 2.0.
*/

import type { Client } from '@elastic/elasticsearch';
import { CoreStart } from '@kbn/core/server';
import { EsLegacyConfigService } from '../../services/es_legacy_config_service';

export function getFallbackUrls(coreStart: CoreStart) {
const esClient = coreStart.elasticsearch.client.asInternalUser as Client;
const [elasticsearchUrl] = getElasticsearchUrl(esClient);
const kibanaUrl = getKibanaUrl(coreStart);
return { elasticsearchUrl, kibanaUrl };
}

function getElasticsearchUrl(esClient: Client): string[] {
const aliveConnections = esClient.connectionPool.connections.filter(
({ status }) => status === 'alive'
);
if (aliveConnections.length) {
return aliveConnections.map(({ url }) => {
const { protocol, host } = new URL(url);
return `${protocol}//${host}`;
});
}

return ['http://localhost:9200'];
}

function getKibanaUrl({ http }: CoreStart) {
export function getFallbackKibanaUrl({ http }: CoreStart) {
const basePath = http.basePath;
const { protocol, hostname, port } = http.getServerInfo();
return `${protocol}://${hostname}:${port}${basePath
// Prepending on '' removes the serverBasePath
.prepend('/')
.slice(0, -1)}`;
}

export async function getFallbackESUrl(
esLegacyConfigService: EsLegacyConfigService
) {
const config = await esLegacyConfigService.readConfig();

return config.hosts;
}
Expand Up @@ -11,7 +11,7 @@ import { ObservabilityOnboardingState } from '../../saved_objects/observability_
import { createObservabilityOnboardingServerRoute } from '../create_observability_onboarding_server_route';
import { createShipperApiKey } from './api_key/create_shipper_api_key';
import { hasLogMonitoringPrivileges } from './api_key/has_log_monitoring_privileges';
import { getFallbackUrls } from './get_fallback_urls';
import { getFallbackKibanaUrl } from './get_fallback_urls';
import { getHasLogs } from './get_has_logs';
import { getObservabilityOnboardingState } from './get_observability_onboarding_state';
import { saveObservabilityOnboardingState } from './save_observability_onboarding_state';
Expand Down Expand Up @@ -52,7 +52,7 @@ const installShipperSetupRoute = createObservabilityOnboardingServerRoute({
const kibanaUrl =
core.setup.http.basePath.publicBaseUrl ?? // priority given to server.publicBaseUrl
plugins.cloud?.setup?.kibanaUrl ?? // then cloud id
getFallbackUrls(coreStart).kibanaUrl; // falls back to local network binding
getFallbackKibanaUrl(coreStart); // falls back to local network binding
const scriptDownloadUrl = `${kibanaUrl}/plugins/observabilityOnboarding/assets/standalone_agent_setup.sh`;
const apiEndpoint = `${kibanaUrl}/internal/observability_onboarding`;

Expand Down
Expand Up @@ -10,7 +10,7 @@ import { getAuthenticationAPIKey } from '../../lib/get_authentication_api_key';
import { createObservabilityOnboardingServerRoute } from '../create_observability_onboarding_server_route';
import { getObservabilityOnboardingState } from '../custom_logs/get_observability_onboarding_state';
import { generateYml } from './generate_yml';
import { getFallbackUrls } from '../custom_logs/get_fallback_urls';
import { getFallbackESUrl } from '../custom_logs/get_fallback_urls';

const generateConfig = createObservabilityOnboardingServerRoute({
endpoint: 'GET /internal/observability_onboarding/elastic_agent/config',
Expand All @@ -26,16 +26,17 @@ const generateConfig = createObservabilityOnboardingServerRoute({
core,
plugins,
request,
services: { esLegacyConfigService },
} = resources;
const authApiKey = getAuthenticationAPIKey(request);

const coreStart = await core.start();
const savedObjectsClient =
coreStart.savedObjects.createInternalRepository();

const elasticsearchUrl =
plugins.cloud?.setup?.elasticsearchUrl ??
getFallbackUrls(coreStart).elasticsearchUrl;
const elasticsearchUrl = plugins.cloud?.setup?.elasticsearchUrl
? [plugins.cloud?.setup?.elasticsearchUrl]
: await getFallbackESUrl(esLegacyConfigService);

const savedState = await getObservabilityOnboardingState({
savedObjectsClient,
Expand All @@ -50,7 +51,7 @@ const generateConfig = createObservabilityOnboardingServerRoute({
apiKey: authApiKey
? `${authApiKey?.apiKeyId}:${authApiKey?.apiKey}`
: '$API_KEY',
esHost: [elasticsearchUrl],
esHost: elasticsearchUrl,
logfileId: `custom-logs-${Date.now()}`,
serviceName: savedState?.state.serviceName,
});
Expand Down
Expand Up @@ -15,6 +15,7 @@ import {
} from '@kbn/server-route-repository';
import * as t from 'io-ts';
import { ObservabilityOnboardingConfig } from '..';
import { EsLegacyConfigService } from '../services/es_legacy_config_service';
import { ObservabilityOnboardingRequestHandlerContext } from '../types';
import { ObservabilityOnboardingRouteHandlerResources } from './types';

Expand All @@ -24,6 +25,9 @@ interface RegisterRoutes {
logger: Logger;
plugins: ObservabilityOnboardingRouteHandlerResources['plugins'];
config: ObservabilityOnboardingConfig;
services: {
esLegacyConfigService: EsLegacyConfigService;
};
}

export function registerRoutes({
Expand All @@ -32,6 +36,7 @@ export function registerRoutes({
logger,
plugins,
config,
services,
}: RegisterRoutes) {
const routes = Object.values(repository);

Expand Down Expand Up @@ -77,6 +82,7 @@ export function registerRoutes({
},
},
config,
services,
})) as any;

if (data === undefined) {
Expand Down
Expand Up @@ -7,6 +7,7 @@
import { CoreSetup, CoreStart, KibanaRequest, Logger } from '@kbn/core/server';
import { ObservabilityOnboardingServerRouteRepository } from '.';
import { ObservabilityOnboardingConfig } from '..';
import { EsLegacyConfigService } from '../services/es_legacy_config_service';
import {
ObservabilityOnboardingPluginSetupDependencies,
ObservabilityOnboardingPluginStartDependencies,
Expand All @@ -32,6 +33,9 @@ export interface ObservabilityOnboardingRouteHandlerResources {
start: () => Promise<CoreStart>;
};
config: ObservabilityOnboardingConfig;
services: {
esLegacyConfigService: EsLegacyConfigService;
};
}

export interface ObservabilityOnboardingRouteCreateOptions {
Expand Down
@@ -0,0 +1,53 @@
/*
* 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 { firstValueFrom, Observable, Subscription } from 'rxjs';
import { ElasticsearchConfig } from '@kbn/core/server';

export class EsLegacyConfigService {
/**
* The elasticsearch config value at a given point in time.
*/
private config?: ElasticsearchConfig;

/**
* An observable that emits elasticsearch config.
*/
private config$?: Observable<ElasticsearchConfig>;

/**
* A reference to the subscription to the elasticsearch observable
*/
private configSub?: Subscription;

setup(config$: Observable<ElasticsearchConfig>) {
this.config$ = config$;
this.configSub = this.config$.subscribe((config) => {
this.config = config;
});
}

stop() {
if (this.configSub) {
this.configSub.unsubscribe();
}
}

async readConfig(): Promise<ElasticsearchConfig> {
if (!this.config$) {
throw new Error(
'Could not read elasticsearch config, this service has not been setup!'
);
}

if (!this.config) {
return firstValueFrom(this.config$);
}

return this.config;
}
}

0 comments on commit 7c16dd9

Please sign in to comment.