[APM] Adds support to install latest prerelease APM package version (#118836) (#120114)

* [APM] Adds support to install latest prerelease APM package version (#117975)

* fixes some type errors

* fixes linting failures

* PR feedback adding shared isPrereleaseVersion function

Co-authored-by: Oliver Gupte <ogupte@users.noreply.github.com>
This commit is contained in:
Kibana Machine 2021-12-01 11:45:25 -05:00 committed by GitHub
parent 62556d89be
commit f0462e0ea2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 104 additions and 11 deletions

View file

@ -24,7 +24,7 @@ export function Instruction({
variantId,
isCloudEnabled,
}) {
const { tutorialService, http, uiSettings, getBasePath } = getServices();
const { tutorialService, http, uiSettings, getBasePath, kibanaVersion } = getServices();
let pre;
if (textPre) {
@ -82,6 +82,7 @@ export function Instruction({
http={http}
variantId={variantId}
isCloudEnabled={isCloudEnabled}
kibanaVersion={kibanaVersion}
/>
</EuiErrorBoundary>
</Suspense>

View file

@ -4,7 +4,12 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import semverParse from 'semver/functions/parse';
export const POLICY_ELASTIC_AGENT_ON_CLOUD = 'policy-elastic-agent-on-cloud';
export const SUPPORTED_APM_PACKAGE_VERSION = '7.16.0';
export function isPrereleaseVersion(version: string) {
return semverParse(version)?.prerelease?.length ?? 0 > 0;
}

View file

@ -72,6 +72,7 @@ function Wrapper({
basePath="http://localhost:5601"
isCloudEnabled={!onPrem}
variantId={apmAgent}
kibanaVersion="8.0.0"
/>
);
}

View file

@ -57,6 +57,7 @@ describe('TutorialConfigAgent', () => {
}
basePath="http://localhost:5601"
isCloudEnabled
kibanaVersion="8.0.0"
/>
);
expect(component.getByTestId('loading')).toBeInTheDocument();
@ -76,6 +77,7 @@ describe('TutorialConfigAgent', () => {
}
basePath="http://localhost:5601"
isCloudEnabled={false}
kibanaVersion="8.0.0"
/>
);
expect(
@ -123,6 +125,7 @@ describe('TutorialConfigAgent', () => {
}
basePath="http://localhost:5601"
isCloudEnabled={false}
kibanaVersion="8.0.0"
/>
);
expect(
@ -158,6 +161,7 @@ describe('TutorialConfigAgent', () => {
}
basePath="http://localhost:5601"
isCloudEnabled
kibanaVersion="8.0.0"
/>
);
expect(
@ -199,6 +203,7 @@ describe('TutorialConfigAgent', () => {
}
basePath="http://localhost:5601"
isCloudEnabled
kibanaVersion="8.0.0"
/>
);
expect(
@ -237,6 +242,7 @@ describe('TutorialConfigAgent', () => {
}
basePath="http://localhost:5601"
isCloudEnabled
kibanaVersion="8.0.0"
/>
);
expect(
@ -271,6 +277,7 @@ describe('TutorialConfigAgent', () => {
}
basePath="http://localhost:5601"
isCloudEnabled
kibanaVersion="8.0.0"
/>
);
expect(
@ -306,6 +313,7 @@ describe('TutorialConfigAgent', () => {
}
basePath="http://localhost:5601"
isCloudEnabled
kibanaVersion="8.0.0"
/>
);
@ -329,6 +337,7 @@ describe('TutorialConfigAgent', () => {
}
basePath="http://localhost:5601"
isCloudEnabled
kibanaVersion="8.0.0"
/>
);
expect(
@ -367,6 +376,7 @@ describe('TutorialConfigAgent', () => {
}
basePath="http://localhost:5601"
isCloudEnabled
kibanaVersion="8.0.0"
/>
);
expect(

View file

@ -9,7 +9,10 @@ import { i18n } from '@kbn/i18n';
import { HttpStart } from 'kibana/public';
import React, { useEffect, useMemo, useState } from 'react';
import styled from 'styled-components';
import { SUPPORTED_APM_PACKAGE_VERSION } from '../../../common/fleet';
import {
isPrereleaseVersion,
SUPPORTED_APM_PACKAGE_VERSION,
} from '../../../common/fleet';
import { APIReturnType } from '../../services/rest/createCallApmApi';
import { getCommands } from './commands/get_commands';
import { getPolicyOptions, PolicyOption } from './get_policy_options';
@ -38,6 +41,7 @@ interface Props {
http: HttpStart;
basePath: string;
isCloudEnabled: boolean;
kibanaVersion: string;
}
const INITIAL_STATE = {
@ -50,10 +54,12 @@ function getFleetLink({
isFleetEnabled,
hasFleetAgents,
basePath,
kibanaVersion,
}: {
isFleetEnabled: boolean;
hasFleetAgents: boolean;
basePath: string;
kibanaVersion: string;
}) {
if (!isFleetEnabled) {
return;
@ -66,7 +72,9 @@ function getFleetLink({
}
: {
label: GET_STARTED_WITH_FLEET_LABEL,
href: `${basePath}/app/integrations#/detail/apm-${SUPPORTED_APM_PACKAGE_VERSION}/overview`,
href: isPrereleaseVersion(kibanaVersion)
? `${basePath}/app/integrations#/detail/apm/overview`
: `${basePath}/app/integrations#/detail/apm-${SUPPORTED_APM_PACKAGE_VERSION}/overview`,
};
}
@ -75,6 +83,7 @@ function TutorialConfigAgent({
http,
basePath,
isCloudEnabled,
kibanaVersion,
}: Props) {
const [data, setData] = useState<APIResponseType>(INITIAL_STATE);
const [isLoading, setIsLoading] = useState(true);
@ -138,6 +147,7 @@ function TutorialConfigAgent({
isFleetEnabled: data.isFleetEnabled,
hasFleetAgents,
basePath,
kibanaVersion,
})}
/>

View file

@ -12,12 +12,14 @@ interface Props {
http: HttpStart;
basePath: string;
isCloudEnabled: boolean;
kibanaVersion: string;
}
function TutorialConfigAgentRumScript({
http,
basePath,
isCloudEnabled,
kibanaVersion,
}: Props) {
return (
<TutorialConfigAgent
@ -25,6 +27,7 @@ function TutorialConfigAgentRumScript({
http={http}
basePath={basePath}
isCloudEnabled={isCloudEnabled}
kibanaVersion={kibanaVersion}
/>
);
}

View file

@ -19,13 +19,17 @@ import { i18n } from '@kbn/i18n';
import { HttpStart } from 'kibana/public';
import React, { useEffect, useState } from 'react';
import styled from 'styled-components';
import { SUPPORTED_APM_PACKAGE_VERSION } from '../../../common/fleet';
import {
isPrereleaseVersion,
SUPPORTED_APM_PACKAGE_VERSION,
} from '../../../common/fleet';
import { APIReturnType } from '../../services/rest/createCallApmApi';
interface Props {
http: HttpStart;
basePath: string;
isDarkTheme: boolean;
kibanaVersion: string;
}
const CentralizedContainer = styled.div`
@ -36,7 +40,12 @@ const CentralizedContainer = styled.div`
type APIResponseType = APIReturnType<'GET /internal/apm/fleet/migration_check'>;
function TutorialFleetInstructions({ http, basePath, isDarkTheme }: Props) {
function TutorialFleetInstructions({
http,
basePath,
isDarkTheme,
kibanaVersion,
}: Props) {
const [data, setData] = useState<APIResponseType | undefined>();
const [isLoading, setIsLoading] = useState(false);
@ -69,6 +78,8 @@ function TutorialFleetInstructions({ http, basePath, isDarkTheme }: Props) {
const apmIntegrationHref = shouldLinkToMigration
? `${basePath}/app/apm/settings/schema`
: isPrereleaseVersion(kibanaVersion)
? `${basePath}/app/integrations#/detail/apm/overview`
: `${basePath}/app/integrations/detail/apm-${SUPPORTED_APM_PACKAGE_VERSION}/overview`;
if (isLoading) {

View file

@ -23,6 +23,7 @@ function Wrapper({ hasFleetPoliciesWithApmIntegration }: Args) {
http={http}
basePath="http://localhost:5601"
isDarkTheme={false}
kibanaVersion="8.0.0"
/>
);
}

View file

@ -176,6 +176,7 @@ export class APMPlugin
ruleDataClient,
plugins: resourcePlugins,
telemetryUsageCounter,
kibanaVersion: this.initContext.env.packageInfo.version,
});
if (plugins.alerting) {
@ -193,6 +194,7 @@ export class APMPlugin
ruleDataClient,
config: currentConfig,
logger: this.logger,
kibanaVersion: this.initContext.env.packageInfo.version,
});
core.deprecations.registerDeprecations({

View file

@ -50,6 +50,7 @@ export function registerRoutes({
config,
ruleDataClient,
telemetryUsageCounter,
kibanaVersion,
}: {
core: APMRouteHandlerResources['core'];
plugins: APMRouteHandlerResources['plugins'];
@ -58,6 +59,7 @@ export function registerRoutes({
config: APMRouteHandlerResources['config'];
ruleDataClient: APMRouteHandlerResources['ruleDataClient'];
telemetryUsageCounter?: TelemetryUsageCounter;
kibanaVersion: string;
}) {
const routes = repository.getRoutes();
@ -115,6 +117,7 @@ export function registerRoutes({
validatedParams
),
ruleDataClient,
kibanaVersion,
}).then((value) => {
return {
aborted: false,

View file

@ -30,6 +30,7 @@ export async function createCloudApmPackgePolicy({
esClient,
logger,
setup,
kibanaVersion,
}: {
cloudPluginSetup: APMPluginSetupDependencies['cloud'];
fleetPluginStart: NonNullable<APMPluginStartDependencies['fleet']>;
@ -37,6 +38,7 @@ export async function createCloudApmPackgePolicy({
esClient: ElasticsearchClient;
logger: Logger;
setup: Setup;
kibanaVersion: string;
}): Promise<PackagePolicy> {
const { attributes } = await savedObjectsClient.get(
APM_SERVER_SCHEMA_SAVED_OBJECT_TYPE,
@ -46,9 +48,11 @@ export async function createCloudApmPackgePolicy({
(attributes as { schemaJson: string }).schemaJson
);
// Merges agent config and source maps with the new APM cloud package policy
const apmPackagePolicyDefinition = getApmPackagePolicyDefinition({
const apmPackagePolicyDefinition = await getApmPackagePolicyDefinition({
apmServerSchema,
cloudPluginSetup,
fleetPluginStart,
kibanaVersion,
});
const mergedAPMPackagePolicy = await mergePackagePolicyWithApm({
setup,

View file

@ -6,20 +6,28 @@
*/
import {
isPrereleaseVersion,
POLICY_ELASTIC_AGENT_ON_CLOUD,
SUPPORTED_APM_PACKAGE_VERSION,
} from '../../../common/fleet';
import { APMPluginSetupDependencies } from '../../types';
import {
APMPluginSetupDependencies,
APMPluginStartDependencies,
} from '../../types';
import { APM_PACKAGE_NAME } from './get_cloud_apm_package_policy';
interface GetApmPackagePolicyDefinitionOptions {
apmServerSchema: Record<string, any>;
cloudPluginSetup: APMPluginSetupDependencies['cloud'];
fleetPluginStart: APMPluginStartDependencies['fleet'];
kibanaVersion: string;
}
export function getApmPackagePolicyDefinition(
export async function getApmPackagePolicyDefinition(
options: GetApmPackagePolicyDefinitionOptions
) {
const { apmServerSchema, cloudPluginSetup } = options;
const { apmServerSchema, cloudPluginSetup, fleetPluginStart, kibanaVersion } =
options;
return {
name: 'Elastic APM',
namespace: 'default',
@ -33,18 +41,37 @@ export function getApmPackagePolicyDefinition(
streams: [],
vars: getApmPackageInputVars({
cloudPluginSetup,
fleetPluginStart,
apmServerSchema: preprocessLegacyFields({ apmServerSchema }),
kibanaVersion,
}),
},
],
package: {
name: APM_PACKAGE_NAME,
version: SUPPORTED_APM_PACKAGE_VERSION,
version: await getApmPackageVersion(fleetPluginStart, kibanaVersion),
title: 'Elastic APM',
},
};
}
async function getApmPackageVersion(
fleetPluginStart: APMPluginStartDependencies['fleet'],
kibanaVersion: string
) {
if (fleetPluginStart && isPrereleaseVersion(kibanaVersion)) {
try {
const latestApmPackage = await fleetPluginStart.fetchFindLatestPackage(
'apm'
);
return latestApmPackage.version;
} catch (error) {
return SUPPORTED_APM_PACKAGE_VERSION;
}
}
return SUPPORTED_APM_PACKAGE_VERSION;
}
export function preprocessLegacyFields({
apmServerSchema,
}: {

View file

@ -25,11 +25,13 @@ export async function registerFleetPolicyCallbacks({
ruleDataClient,
config,
logger,
kibanaVersion,
}: {
plugins: APMRouteHandlerResources['plugins'];
ruleDataClient: APMRouteHandlerResources['ruleDataClient'];
config: NonNullable<APMPlugin['currentConfig']>;
logger: NonNullable<APMPlugin['logger']>;
kibanaVersion: string;
}) {
if (!plugins.fleet) {
return;
@ -45,6 +47,7 @@ export async function registerFleetPolicyCallbacks({
ruleDataClient,
config,
logger,
kibanaVersion,
});
// Registers a callback invoked when a policy is updated to populate the APM
@ -56,6 +59,7 @@ export async function registerFleetPolicyCallbacks({
ruleDataClient,
config,
logger,
kibanaVersion,
});
}
@ -73,6 +77,7 @@ function registerPackagePolicyExternalCallback({
ruleDataClient,
config,
logger,
kibanaVersion,
}: {
fleetPluginStart: NonNullable<APMPluginStartDependencies['fleet']>;
callbackName: 'packagePolicyCreate' | 'packagePolicyUpdate';
@ -80,6 +85,7 @@ function registerPackagePolicyExternalCallback({
ruleDataClient: APMRouteHandlerResources['ruleDataClient'];
config: NonNullable<APMPlugin['currentConfig']>;
logger: NonNullable<APMPlugin['logger']>;
kibanaVersion: string;
}) {
const callbackFn:
| PostPackagePolicyCreateCallback
@ -100,6 +106,7 @@ function registerPackagePolicyExternalCallback({
config,
logger,
ruleDataClient,
kibanaVersion,
});
return await mergePackagePolicyWithApm({
setup,

View file

@ -165,7 +165,8 @@ const createCloudApmPackagePolicyRoute = createApmServerRoute({
endpoint: 'POST /internal/apm/fleet/cloud_apm_package_policy',
options: { tags: ['access:apm', 'access:apm_write'] },
handler: async (resources) => {
const { plugins, context, config, request, logger } = resources;
const { plugins, context, config, request, logger, kibanaVersion } =
resources;
const cloudApmMigrationEnabled = config.agent.migrations.enabled;
if (!plugins.fleet || !plugins.security) {
throw Boom.internal(FLEET_SECURITY_REQUIRED_MESSAGE);
@ -192,6 +193,7 @@ const createCloudApmPackagePolicyRoute = createApmServerRoute({
esClient,
logger,
setup,
kibanaVersion,
});
return { cloudApmPackagePolicy };

View file

@ -69,4 +69,5 @@ export interface APMRouteHandlerResources {
};
ruleDataClient: IRuleDataClient;
telemetryUsageCounter?: TelemetryUsageCounter;
kibanaVersion: string;
}

View file

@ -85,6 +85,7 @@ import { FleetArtifactsClient } from './services/artifacts';
import type { FleetRouter } from './types/request_context';
import { TelemetryEventsSender } from './telemetry/sender';
import { setupFleet } from './services/setup';
import { fetchFindLatestPackage } from './services/epm/registry';
export interface FleetSetupDeps {
licensing: LicensingPluginSetup;
@ -165,6 +166,8 @@ export interface FleetStartContract {
* @param packageName
*/
createArtifactsClient: (packageName: string) => FleetArtifactsClient;
fetchFindLatestPackage: typeof fetchFindLatestPackage;
}
export class FleetPlugin
@ -382,6 +385,7 @@ export class FleetPlugin
createArtifactsClient(packageName: string) {
return new FleetArtifactsClient(core.elasticsearch.client.asInternalUser, packageName);
},
fetchFindLatestPackage,
};
}

View file

@ -167,6 +167,7 @@ export const createMockFleetStartContract = (indexPattern: string): FleetStartCo
registerExternalCallback: jest.fn((...args: ExternalCallback) => {}),
packagePolicyService: createPackagePolicyServiceMock(),
createArtifactsClient: jest.fn().mockReturnValue(createArtifactsClientMock()),
fetchFindLatestPackage: jest.fn().mockReturnValue('8.0.0'),
};
};