diff --git a/x-pack/platform/plugins/shared/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/processors/ip_location.tsx b/x-pack/platform/plugins/shared/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/processors/ip_location.tsx index 5993d73f980a7..316b1449ef463 100644 --- a/x-pack/platform/plugins/shared/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/processors/ip_location.tsx +++ b/x-pack/platform/plugins/shared/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/processors/ip_location.tsx @@ -27,26 +27,38 @@ import { from, to } from './shared'; import { TargetField } from './common_fields/target_field'; import { PropertiesField } from './common_fields/properties_field'; import type { GeoipDatabase } from '../../../../../../../common/types'; -import { getDatabaseText, getDatabaseValue } from '../../../../../sections/manage_processors/utils'; +import { + getDatabaseOptionLabel, + getDatabaseText, + getDatabaseValue, + normalizeMmdbFilename, + MMDB_EXTENSION, +} from '../../../../../sections/manage_processors/utils'; import { getTypeLabel } from '../../../../../sections/manage_processors/constants'; -const extension = '.mmdb'; - const fieldsConfig: FieldsConfig = { /* Optional field config */ database_file: { type: FIELD_TYPES.COMBO_BOX, deserializer: (v: unknown) => to.arrayOfStrings(v).map((str) => { - const databaseName = str?.split(extension)[0]; - // Use the translated text for this database, if it exists - return getDatabaseText(databaseName) ?? databaseName; + const databaseName = str.split(MMDB_EXTENSION)[0]; + const knownDatabaseText = getDatabaseText(databaseName); + // Known managed DB → return display text (e.g. "ASN" for standard_asn) + // Local DB → return full filename (e.g. "ASN.mmdb") to match the combo box label + return knownDatabaseText ?? str; }), serializer: (v: any[]) => { if (v.length) { const databaseName = v[0]; + // Local databases have the extension already in the label + if (typeof databaseName === 'string' && databaseName.endsWith(MMDB_EXTENSION)) { + return normalizeMmdbFilename(databaseName); + } const databaseValue = getDatabaseValue(databaseName); - return databaseValue ? `${databaseValue}${extension}` : `${databaseName}${extension}`; + return databaseValue + ? `${databaseValue}${MMDB_EXTENSION}` + : `${databaseName}${MMDB_EXTENSION}`; } return undefined; }, @@ -92,8 +104,8 @@ export const IpLocation: FunctionComponent = () => { const dataAsOptions = (data || []).map((item) => ({ id: item.id, type: item.type, - // Use the translated text for this database, if it exists - label: getDatabaseText(item.name) ?? item.name, + // Use the name of the database file for local databases and the translated text for others, if it exists + label: getDatabaseOptionLabel(item), })); const optionsByGroup = groupBy(dataAsOptions, 'type'); const groupedOptions = map(optionsByGroup, (items, groupName) => ({ diff --git a/x-pack/platform/plugins/shared/ingest_pipelines/public/application/sections/manage_processors/utils.test.ts b/x-pack/platform/plugins/shared/ingest_pipelines/public/application/sections/manage_processors/utils.test.ts index c5b12a95bc539..4667924cf2361 100644 --- a/x-pack/platform/plugins/shared/ingest_pipelines/public/application/sections/manage_processors/utils.test.ts +++ b/x-pack/platform/plugins/shared/ingest_pipelines/public/application/sections/manage_processors/utils.test.ts @@ -5,7 +5,12 @@ * 2.0. */ -import { getDatabaseValue, getDatabaseText } from './utils'; +import { + getDatabaseOptionLabel, + getDatabaseText, + getDatabaseValue, + normalizeMmdbFilename, +} from './utils'; describe('getDatabaseValue', () => { it('should return the value for a given database text for maxmind', () => { @@ -58,3 +63,38 @@ describe('getDatabaseText', () => { expect(result).toBe('IP Geolocation'); }); }); + +describe('normalizeMmdbFilename', () => { + it('should add .mmdb when missing', () => { + expect(normalizeMmdbFilename('GeoLite2-City')).toBe('GeoLite2-City.mmdb'); + }); + + it('should keep a single .mmdb suffix', () => { + expect(normalizeMmdbFilename('GeoLite2-City.mmdb')).toBe('GeoLite2-City.mmdb'); + }); + + it('should collapse repeated .mmdb suffixes', () => { + expect(normalizeMmdbFilename('GeoLite2-City.mmdb.mmdb')).toBe('GeoLite2-City.mmdb'); + }); +}); + +describe('getDatabaseOptionLabel', () => { + it('should return the database filename for local databases', () => { + expect(getDatabaseOptionLabel({ type: 'local', name: 'GeoLite2-City' })).toBe( + 'GeoLite2-City.mmdb' + ); + expect(getDatabaseOptionLabel({ type: 'local', name: 'GeoLite2-City.mmdb' })).toBe( + 'GeoLite2-City.mmdb' + ); + }); + + it('should return translated text for known managed databases', () => { + expect(getDatabaseOptionLabel({ type: 'maxmind', name: 'standard_asn' })).toBe('ASN'); + }); + + it('should fallback to name when no translation exists', () => { + expect(getDatabaseOptionLabel({ type: 'maxmind', name: 'something_else' })).toBe( + 'something_else' + ); + }); +}); diff --git a/x-pack/platform/plugins/shared/ingest_pipelines/public/application/sections/manage_processors/utils.ts b/x-pack/platform/plugins/shared/ingest_pipelines/public/application/sections/manage_processors/utils.ts index 8ac853bbac17c..6387c3eb40786 100644 --- a/x-pack/platform/plugins/shared/ingest_pipelines/public/application/sections/manage_processors/utils.ts +++ b/x-pack/platform/plugins/shared/ingest_pipelines/public/application/sections/manage_processors/utils.ts @@ -8,6 +8,9 @@ import type { DatabaseType, DatabaseNameOption } from '../../../../common/types'; import { GEOIP_NAME_OPTIONS, IPINFO_NAME_OPTIONS } from './constants'; +export const MMDB_EXTENSION = '.mmdb'; +const mmdbSuffixRegExp = /(\.mmdb)+$/; + const getDatabaseNameOptions = (type?: DatabaseType): DatabaseNameOption[] => { switch (type) { case 'maxmind': @@ -42,3 +45,29 @@ export const getDatabaseText = (databaseValue: string, type?: DatabaseType): str const options = getDatabaseNameOptions(type); return options.find((opt) => opt.value === databaseValue)?.text; }; + +/** + * Returns the normalized filename of the database. + * @param name The name of the database + * @returns The normalized filename of the database + */ +export const normalizeMmdbFilename = (name: string) => { + if (name.endsWith(MMDB_EXTENSION)) { + return name.replace(mmdbSuffixRegExp, MMDB_EXTENSION); + } + + return `${name}${MMDB_EXTENSION}`; +}; + +/** + * Returns the label of the database, if it exists. + * @param item The database item + * @returns The label of the database + */ +export const getDatabaseOptionLabel = (item: { type: DatabaseType; name: string }) => { + if (item.type === 'local') { + return normalizeMmdbFilename(item.name); + } + + return getDatabaseText(item.name) ?? item.name; +};