Skip to content

Commit

Permalink
Merge branch 'master' into fix-migration-bug
Browse files Browse the repository at this point in the history
  • Loading branch information
kibanamachine authored Oct 15, 2021
2 parents 4faaebc + 712fac6 commit 675406d
Show file tree
Hide file tree
Showing 35 changed files with 989 additions and 109 deletions.
Original file line number Diff line number Diff line change
@@ -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 { extractEntityAndBoundaryReferences } from './migrations';

describe('geo_containment migration utilities', () => {
test('extractEntityAndBoundaryReferences', () => {
expect(
extractEntityAndBoundaryReferences({
index: 'foo*',
indexId: 'foobar',
geoField: 'geometry',
entity: 'vehicle_id',
dateField: '@timestamp',
boundaryType: 'entireIndex',
boundaryIndexTitle: 'boundary*',
boundaryIndexId: 'boundaryid',
boundaryGeoField: 'geometry',
})
).toEqual({
params: {
boundaryGeoField: 'geometry',
boundaryIndexRefName: 'boundary_index_boundaryid',
boundaryIndexTitle: 'boundary*',
boundaryType: 'entireIndex',
dateField: '@timestamp',
entity: 'vehicle_id',
geoField: 'geometry',
index: 'foo*',
indexRefName: 'tracked_index_foobar',
},
references: [
{
id: 'foobar',
name: 'param:tracked_index_foobar',
type: 'index-pattern',
},
{
id: 'boundaryid',
name: 'param:boundary_index_boundaryid',
type: 'index-pattern',
},
],
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* 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 {
SavedObjectAttributes,
SavedObjectReference,
SavedObjectUnsanitizedDoc,
} from 'kibana/server';
import { AlertTypeParams } from '../../index';
import { Query } from '../../../../../../src/plugins/data/common/query';
import { RawAlert } from '../../types';

// These definitions are dupes of the SO-types in stack_alerts/geo_containment
// There are not exported to avoid deep imports from stack_alerts plugins into here
const GEO_CONTAINMENT_ID = '.geo-containment';
interface GeoContainmentParams extends AlertTypeParams {
index: string;
indexId: string;
geoField: string;
entity: string;
dateField: string;
boundaryType: string;
boundaryIndexTitle: string;
boundaryIndexId: string;
boundaryGeoField: string;
boundaryNameField?: string;
indexQuery?: Query;
boundaryIndexQuery?: Query;
}
type GeoContainmentExtractedParams = Omit<GeoContainmentParams, 'indexId' | 'boundaryIndexId'> & {
indexRefName: string;
boundaryIndexRefName: string;
};

export function extractEntityAndBoundaryReferences(params: GeoContainmentParams): {
params: GeoContainmentExtractedParams;
references: SavedObjectReference[];
} {
const { indexId, boundaryIndexId, ...otherParams } = params;

const indexRefNamePrefix = 'tracked_index_';
const boundaryRefNamePrefix = 'boundary_index_';

// Since these are stack-alerts, we need to prefix with the `param:`-namespace
const references = [
{
name: `param:${indexRefNamePrefix}${indexId}`,
type: `index-pattern`,
id: indexId as string,
},
{
name: `param:${boundaryRefNamePrefix}${boundaryIndexId}`,
type: 'index-pattern',
id: boundaryIndexId as string,
},
];
return {
params: {
...otherParams,
indexRefName: `${indexRefNamePrefix}${indexId}`,
boundaryIndexRefName: `${boundaryRefNamePrefix}${boundaryIndexId}`,
},
references,
};
}

export function extractRefsFromGeoContainmentAlert(
doc: SavedObjectUnsanitizedDoc<RawAlert>
): SavedObjectUnsanitizedDoc<RawAlert> {
if (doc.attributes.alertTypeId !== GEO_CONTAINMENT_ID) {
return doc;
}

const {
attributes: { params },
} = doc;

const { params: newParams, references } = extractEntityAndBoundaryReferences(
params as GeoContainmentParams
);
return {
...doc,
attributes: {
...doc.attributes,
params: newParams as SavedObjectAttributes,
},
references: [...(doc.references || []), ...references],
};
}
90 changes: 90 additions & 0 deletions x-pack/plugins/alerting/server/saved_objects/migrations.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1913,6 +1913,96 @@ describe('successful migrations', () => {
],
});
});

test('geo-containment alert migration extracts boundary and index references', () => {
const migration7160 = getMigrations(encryptedSavedObjectsSetup, isPreconfigured)['7.16.0'];
const alert = {
...getMockData({
alertTypeId: '.geo-containment',
params: {
indexId: 'foo',
boundaryIndexId: 'bar',
},
}),
};

const migratedAlert = migration7160(alert, migrationContext);

expect(migratedAlert.references).toEqual([
{ id: 'foo', name: 'param:tracked_index_foo', type: 'index-pattern' },
{ id: 'bar', name: 'param:boundary_index_bar', type: 'index-pattern' },
]);

expect(migratedAlert.attributes.params).toEqual({
boundaryIndexRefName: 'boundary_index_bar',
indexRefName: 'tracked_index_foo',
});

expect(migratedAlert.attributes.params.indexId).toEqual(undefined);
expect(migratedAlert.attributes.params.boundaryIndexId).toEqual(undefined);
});

test('geo-containment alert migration should preserve foreign references', () => {
const migration7160 = getMigrations(encryptedSavedObjectsSetup, isPreconfigured)['7.16.0'];
const alert = {
...getMockData({
alertTypeId: '.geo-containment',
params: {
indexId: 'foo',
boundaryIndexId: 'bar',
},
}),
references: [
{
name: 'foreign-name',
id: '999',
type: 'foreign-name',
},
],
};

const migratedAlert = migration7160(alert, migrationContext);

expect(migratedAlert.references).toEqual([
{
name: 'foreign-name',
id: '999',
type: 'foreign-name',
},
{ id: 'foo', name: 'param:tracked_index_foo', type: 'index-pattern' },
{ id: 'bar', name: 'param:boundary_index_bar', type: 'index-pattern' },
]);

expect(migratedAlert.attributes.params).toEqual({
boundaryIndexRefName: 'boundary_index_bar',
indexRefName: 'tracked_index_foo',
});

expect(migratedAlert.attributes.params.indexId).toEqual(undefined);
expect(migratedAlert.attributes.params.boundaryIndexId).toEqual(undefined);
});

test('geo-containment alert migration ignores other alert-types', () => {
const migration7160 = getMigrations(encryptedSavedObjectsSetup, isPreconfigured)['7.16.0'];
const alert = {
...getMockData({
alertTypeId: '.foo',
references: [
{
name: 'foreign-name',
id: '999',
type: 'foreign-name',
},
],
}),
};

const migratedAlert = migration7160(alert, migrationContext);

expect(typeof migratedAlert.attributes.legacyId).toEqual('string'); // introduced by setLegacyId migration
delete migratedAlert.attributes.legacyId;
expect(migratedAlert).toEqual(alert);
});
});

describe('8.0.0', () => {
Expand Down
4 changes: 3 additions & 1 deletion x-pack/plugins/alerting/server/saved_objects/migrations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
import { RawAlert, RawAlertAction } from '../types';
import { EncryptedSavedObjectsPluginSetup } from '../../../encrypted_saved_objects/server';
import type { IsMigrationNeededPredicate } from '../../../encrypted_saved_objects/server';
import { extractRefsFromGeoContainmentAlert } from './geo_containment/migrations';

const SIEM_APP_ID = 'securitySolution';
const SIEM_SERVER_APP_ID = 'siem';
Expand Down Expand Up @@ -117,7 +118,8 @@ export function getMigrations(
pipeMigrations(
setLegacyId,
getRemovePreconfiguredConnectorsFromReferencesFn(isPreconfigured),
addRuleIdsToLegacyNotificationReferences
addRuleIdsToLegacyNotificationReferences,
extractRefsFromGeoContainmentAlert
)
);

Expand Down
9 changes: 8 additions & 1 deletion x-pack/plugins/fleet/common/services/license.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import type { Observable, Subscription } from 'rxjs';

import type { ILicense } from '../../../licensing/common/types';
import type { ILicense, LicenseType } from '../../../licensing/common/types';

// Generic license service class that works with the license observable
// Both server and client plugins instancates a singleton version of this class
Expand Down Expand Up @@ -53,4 +53,11 @@ export class LicenseService {
this.licenseInformation?.hasAtLeast('enterprise')
);
}
public hasAtLeast(licenseType: LicenseType) {
return (
this.licenseInformation?.isAvailable &&
this.licenseInformation?.isActive &&
this.licenseInformation?.hasAtLeast(licenseType)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ describe('Fleet - packageToPackagePolicy', () => {
transform: [],
ilm_policy: [],
data_stream_ilm_policy: [],
ml_model: [],
},
},
status: 'not_installed',
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/fleet/common/types/models/epm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ export enum ElasticsearchAssetType {
ilmPolicy = 'ilm_policy',
transform = 'transform',
dataStreamIlmPolicy = 'data_stream_ilm_policy',
mlModel = 'ml_model',
}

export type DataType = typeof dataTypes;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
EuiFieldText,
EuiForm,
EuiFormErrorText,
EuiButtonGroup,
} from '@elastic/eui';
import type { EuiStepProps } from '@elastic/eui/src/components/steps/step';
import styled from 'styled-components';
Expand Down Expand Up @@ -193,19 +194,11 @@ export const FleetServerCommandStep = ({
/>
</EuiText>
<EuiSpacer size="l" />
<EuiSelect
prepend={
<EuiText>
<FormattedMessage
id="xpack.fleet.fleetServerSetup.platformSelectLabel"
defaultMessage="Platform"
/>
</EuiText>
}
<EuiButtonGroup
options={PLATFORM_OPTIONS}
value={platform}
onChange={(e) => setPlatform(e.target.value as PLATFORM_TYPE)}
aria-label={i18n.translate('xpack.fleet.fleetServerSetup.platformSelectAriaLabel', {
idSelected={platform}
onChange={(id) => setPlatform(id as PLATFORM_TYPE)}
legend={i18n.translate('xpack.fleet.fleetServerSetup.platformSelectAriaLabel', {
defaultMessage: 'Platform',
})}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,11 @@ export const AssetsFacetGroup = ({ width }: Args) => {
elasticsearch: {
component_template: [],
data_stream_ilm_policy: [],
data_stream: [],
ilm_policy: [],
index_template: [],
ingest_pipeline: [],
transform: [],
ml_model: [],
},
}}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ export const AssetTitleMap: Record<DisplayedAssetType, string> = {
ml_module: i18n.translate('xpack.fleet.epm.assetTitles.mlModules', {
defaultMessage: 'ML modules',
}),
ml_model: i18n.translate('xpack.fleet.epm.assetTitles.mlModels', {
defaultMessage: 'ML models',
}),
view: i18n.translate('xpack.fleet.epm.assetTitles.views', {
defaultMessage: 'Views',
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import React from 'react';
import styled from 'styled-components';
import { EuiText, EuiSpacer, EuiLink, EuiCodeBlock, EuiSelect } from '@elastic/eui';
import { EuiText, EuiSpacer, EuiLink, EuiCodeBlock, EuiButtonGroup } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';

Expand Down Expand Up @@ -51,19 +51,11 @@ export const ManualInstructions: React.FunctionComponent<Props> = ({
/>
</EuiText>
<EuiSpacer size="l" />
<EuiSelect
prepend={
<EuiText>
<FormattedMessage
id="xpack.fleet.enrollmentInstructions.platformSelectLabel"
defaultMessage="Platform"
/>
</EuiText>
}
<EuiButtonGroup
options={PLATFORM_OPTIONS}
value={platform}
onChange={(e) => setPlatform(e.target.value as PLATFORM_TYPE)}
aria-label={i18n.translate('xpack.fleet.enrollmentInstructions.platformSelectAriaLabel', {
idSelected={platform}
onChange={(id) => setPlatform(id as PLATFORM_TYPE)}
legend={i18n.translate('xpack.fleet.enrollmentInstructions.platformSelectAriaLabel', {
defaultMessage: 'Platform',
})}
/>
Expand Down
Loading

0 comments on commit 675406d

Please sign in to comment.