Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -155,12 +155,13 @@ export class MbMap extends Component<Props, State> {

async _createMbMapInstance(initialView: MapCenterAndZoom | null): Promise<MapboxMap> {
this._reportUsage();
const glyphsUrlTemplate = await getGlyphUrl();
return new Promise((resolve) => {
const mbStyle = {
version: 8 as 8,
sources: {},
layers: [],
glyphs: getGlyphUrl(),
glyphs: glyphsUrlTemplate,
};

const options: MapOptions = {
Expand Down
66 changes: 47 additions & 19 deletions x-pack/plugins/maps/public/util.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,60 +5,88 @@
* 2.0.
*/

import { getGlyphUrl, makePublicExecutionContext } from './util';

const MOCK_EMS_SETTINGS = {
isEMSEnabled: () => true,
};
import {
getGlyphUrl,
makePublicExecutionContext,
testOnlyClearCanAccessEmsFontsPromise,
} from './util';

describe('getGlyphUrl', () => {
describe('EMS enabled', () => {
beforeAll(() => {
beforeEach(() => {
require('./kibana_services').getHttp = () => ({
basePath: {
prepend: (url) => url, // No need to actually prepend a dev basepath for test
prepend: (path) => `abc${path}`,
},
});
testOnlyClearCanAccessEmsFontsPromise();
});

describe('EMS proxy disabled', () => {
describe('offline', () => {
beforeAll(() => {
require('./kibana_services').getEMSSettings = () => {
return {
getEMSFontLibraryUrl() {
return 'foobar';
return 'https://tiles.maps.elastic.co/fonts/{fontstack}/{range}.pbf';
},
isEMSEnabled() {
return true;
},
};
};
require('node-fetch').default = () => {
throw new Error('Simulated offline environment with no EMS access');
};
});

test('should return EMS fonts URL', async () => {
expect(getGlyphUrl()).toBe('foobar');
test('should return kibana fonts template URL', async () => {
expect(await getGlyphUrl()).toBe('abc/api/maps/fonts/{fontstack}/{range}');
});
});

describe('online', () => {
beforeAll(() => {
require('./kibana_services').getEMSSettings = () => {
return {
getEMSFontLibraryUrl() {
return 'https://tiles.maps.elastic.co/fonts/{fontstack}/{range}.pbf';
},
isEMSEnabled() {
return true;
},
};
};
require('node-fetch').default = () => {
return Promise.resolve({ status: 200 });
};
});

test('should return EMS fonts template URL', async () => {
expect(await getGlyphUrl()).toBe(
'https://tiles.maps.elastic.co/fonts/{fontstack}/{range}.pbf'
);
});
});
});

describe('EMS disabled', () => {
beforeAll(() => {
const mockHttp = {
basePath: {
prepend: (path) => `abc${path}`,
},
require('./kibana_services').getHttp = () => {
return {
basePath: {
prepend: (path) => `abc${path}`,
},
};
};
require('./kibana_services').getHttp = () => mockHttp;
require('./kibana_services').getEMSSettings = () => {
return {
...MOCK_EMS_SETTINGS,
isEMSEnabled: () => false,
};
};
});

test('should return kibana fonts URL', async () => {
expect(getGlyphUrl()).toBe('abc/api/maps/fonts/{fontstack}/{range}');
test('should return kibana fonts template URL', async () => {
expect(await getGlyphUrl()).toBe('abc/api/maps/fonts/{fontstack}/{range}');
});
});
});
Expand Down
42 changes: 40 additions & 2 deletions x-pack/plugins/maps/public/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* 2.0.
*/

import fetch from 'node-fetch';
import { EMSClient, FileLayer, TMSService } from '@elastic/ems-client';
import type { KibanaExecutionContext } from '@kbn/core/public';
import { FONTS_API_PATH } from '../common/constants';
Expand Down Expand Up @@ -60,9 +61,46 @@ async function getEMSClient(): Promise<EMSClient> {
return emsClient;
}

export function getGlyphUrl(): string {
let canAccessEmsFontsPromise: Promise<boolean> | null = null;
async function canAccessEmsFonts(): Promise<boolean> {
if (!canAccessEmsFontsPromise) {
canAccessEmsFontsPromise = new Promise(async (resolve) => {
try {
const emsSettings = getEMSSettings();
if (!emsSettings!.isEMSEnabled()) {
resolve(false);
}
const emsFontUrlTemplate = emsSettings!.getEMSFontLibraryUrl();

const emsFontUrl = emsFontUrlTemplate
.replace('{fontstack}', 'Open Sans')
.replace('{range}', '0-255');
const resp = await fetch(emsFontUrl, {
method: 'HEAD',
});
if (resp.status >= 400) {
throw new Error(`status: ${resp.status}`);
}
resolve(true);
} catch (error) {
// eslint-disable-next-line no-console
console.warn(
`Unable to access fonts from Elastic Maps Service (EMS). Set kibana.yml 'map.includeElasticMapsService: false' to avoid unnecessary EMS requests.`
);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit. This warning will only be visible in the browser console of a client which might not be the best audience. Since we're suggesting changing kibana.yml, maybe we should instead log this warning in the kibana log where an administrator might see it?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you know if its possible to write kibana logs from the client?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh right. nevermind. also, after more consideration, I realize this is definitely more related to the client's environment as they might not have external internet access, but other clients accessing the kibana cluster may have access. so the warning would probably not be very useful for admins.

resolve(false);
}
});
}
return canAccessEmsFontsPromise;
}
// test only function to reset singleton for different test cases.
export function testOnlyClearCanAccessEmsFontsPromise() {
canAccessEmsFontsPromise = null;
}

export async function getGlyphUrl(): Promise<string> {
const emsSettings = getEMSSettings();
if (!emsSettings!.isEMSEnabled()) {
if (!emsSettings!.isEMSEnabled() || !(await canAccessEmsFonts())) {
return getHttp().basePath.prepend(`/${FONTS_API_PATH}/{fontstack}/{range}`);
}

Expand Down