mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[Maps] add ability to load EMS resources with CORS (#34503)
- breaking change: by default, the Maps app now connects with CORS to EMS. This is optional - no longer include the kbn-version header when requesting files over CORS in region maps
This commit is contained in:
parent
e64d6b2cd1
commit
e2e5fed76f
20 changed files with 422 additions and 151 deletions
|
@ -209,6 +209,7 @@ export default () => Joi.object({
|
|||
}).default(),
|
||||
map: Joi.object({
|
||||
includeElasticMapsService: Joi.boolean().default(true),
|
||||
proxyElasticMapsServiceInMaps: Joi.boolean().default(false),
|
||||
tilemap: Joi.object({
|
||||
url: Joi.string(),
|
||||
options: Joi.object({
|
||||
|
|
|
@ -18,12 +18,7 @@
|
|||
*/
|
||||
|
||||
import expect from '@kbn/expect';
|
||||
import EMS_CATALOGUE from './ems_mocks/sample_manifest.json';
|
||||
import EMS_FILES from './ems_mocks/sample_files.json';
|
||||
import EMS_TILES from './ems_mocks/sample_tiles.json';
|
||||
|
||||
|
||||
import { EMSClient } from '../../../../../core_plugins/tile_map/common/ems_client';
|
||||
import { getEMSClient } from './ems_client_util';
|
||||
|
||||
describe('ems_client', () => {
|
||||
|
||||
|
@ -178,27 +173,3 @@ describe('ems_client', () => {
|
|||
|
||||
});
|
||||
|
||||
|
||||
function getEMSClient(options = {}) {
|
||||
|
||||
const emsClient = new EMSClient({
|
||||
language: 'en',
|
||||
kbnVersion: '7.x.x',
|
||||
manifestServiceUrl: 'https://foobar',
|
||||
htmlSanitizer: x => x,
|
||||
landingPageUrl: 'https://landing.foobar',
|
||||
...options
|
||||
});
|
||||
|
||||
emsClient._getManifest = async (url) => {
|
||||
//simulate network calls
|
||||
if (url.startsWith('https://foobar')) {
|
||||
return EMS_CATALOGUE;
|
||||
} else if (url.startsWith('https://tiles.foobar')) {
|
||||
return EMS_TILES;
|
||||
} else if (url.startsWith('https://files.foobar')) {
|
||||
return EMS_FILES;
|
||||
}
|
||||
};
|
||||
return emsClient;
|
||||
}
|
||||
|
|
49
src/legacy/ui/public/vis/__tests__/map/ems_client_util.js
Normal file
49
src/legacy/ui/public/vis/__tests__/map/ems_client_util.js
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
|
||||
import { EMSClient } from '../../../../../core_plugins/tile_map/common/ems_client';
|
||||
|
||||
import EMS_CATALOGUE from './ems_mocks/sample_manifest.json';
|
||||
import EMS_FILES from './ems_mocks/sample_files.json';
|
||||
import EMS_TILES from './ems_mocks/sample_tiles.json';
|
||||
|
||||
export function getEMSClient(options = {}) {
|
||||
|
||||
const emsClient = new EMSClient({
|
||||
language: 'en',
|
||||
kbnVersion: '7.x.x',
|
||||
manifestServiceUrl: 'https://foobar',
|
||||
htmlSanitizer: x => x,
|
||||
landingPageUrl: 'https://landing.foobar',
|
||||
...options
|
||||
});
|
||||
|
||||
emsClient._getManifest = async (url) => {
|
||||
//simulate network calls
|
||||
if (url.startsWith('https://foobar')) {
|
||||
return EMS_CATALOGUE;
|
||||
} else if (url.startsWith('https://tiles.foobar')) {
|
||||
return EMS_TILES;
|
||||
} else if (url.startsWith('https://files.foobar')) {
|
||||
return EMS_FILES;
|
||||
}
|
||||
};
|
||||
return emsClient;
|
||||
}
|
21
src/legacy/ui/public/vis/map/ems_client.js
Normal file
21
src/legacy/ui/public/vis/map/ems_client.js
Normal file
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
|
||||
export { EMSClient } from '../../../../core_plugins/tile_map/common/ems_client';
|
|
@ -32,7 +32,7 @@ const markdownIt = new MarkdownIt({
|
|||
const TMS_IN_YML_ID = 'TMS in config/kibana.yml';
|
||||
|
||||
uiModules.get('kibana')
|
||||
.service('serviceSettings', function ($http, $sanitize, mapConfig, tilemapsConfig, kbnVersion) {
|
||||
.service('serviceSettings', function ($sanitize, mapConfig, tilemapsConfig, kbnVersion) {
|
||||
|
||||
const attributionFromConfig = $sanitize(markdownIt.render(tilemapsConfig.deprecated.config.options.attribution || ''));
|
||||
const tmsOptionsFromConfig = _.assign({}, tilemapsConfig.deprecated.config.options, { attribution: attributionFromConfig });
|
||||
|
@ -215,11 +215,8 @@ uiModules.get('kibana')
|
|||
|
||||
async getJsonForRegionLayer(fileLayerConfig) {
|
||||
const url = await this.getUrlForRegionLayer(fileLayerConfig);
|
||||
const json = await $http({
|
||||
url: url,
|
||||
method: 'GET'
|
||||
});
|
||||
return json.data;
|
||||
const response = await fetch(url);
|
||||
return await response.json();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,8 +5,14 @@
|
|||
*/
|
||||
|
||||
export const GIS_API_PATH = 'api/maps';
|
||||
export const EMS_DATA_FILE_PATH = 'ems/file';
|
||||
export const EMS_DATA_TMS_PATH = 'ems/tms';
|
||||
export const EMS_META_PATH = 'ems/meta';
|
||||
|
||||
export const MAP_SAVED_OBJECT_TYPE = 'map';
|
||||
export const APP_ID = 'maps';
|
||||
export const APP_ICON = 'gisApp';
|
||||
|
||||
export function createMapPath(id) {
|
||||
return `/app/maps#/map/${id}`;
|
||||
}
|
||||
|
@ -14,19 +20,13 @@ export function createMapPath(id) {
|
|||
export const EMS_FILE = 'EMS_FILE';
|
||||
export const ES_GEO_GRID = 'ES_GEO_GRID';
|
||||
export const ES_SEARCH = 'ES_SEARCH';
|
||||
export const SOURCE_DATA_ID_ORIGIN = 'source';
|
||||
|
||||
export const DECIMAL_DEGREES_PRECISION = 5; // meters precision
|
||||
|
||||
export const ZOOM_PRECISION = 2;
|
||||
|
||||
export const DEFAULT_EMS_TILE_LAYER = 'road_map';
|
||||
|
||||
export const APP_ID = 'maps';
|
||||
|
||||
export const APP_ICON = 'gisApp';
|
||||
|
||||
export const SOURCE_DATA_ID_ORIGIN = 'source';
|
||||
|
||||
export const FEATURE_ID_PROPERTY_NAME = '__kbn__feature_id__';
|
||||
|
||||
export const ES_GEO_FIELD_TYPE = {
|
||||
|
|
58
x-pack/plugins/maps/common/ems_util.js
Normal file
58
x-pack/plugins/maps/common/ems_util.js
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
|
||||
import { EMS_DATA_FILE_PATH, EMS_DATA_TMS_PATH, GIS_API_PATH } from './constants';
|
||||
|
||||
export async function getEMSResources(emsClient, includeElasticMapsService, licenseUid, useRelativePathToProxy) {
|
||||
|
||||
if (!includeElasticMapsService) {
|
||||
return {
|
||||
fileLayers: [],
|
||||
tmsServices: []
|
||||
};
|
||||
}
|
||||
|
||||
emsClient.addQueryParams({ license: licenseUid });
|
||||
const fileLayerObjs = await emsClient.getFileLayers();
|
||||
const tmsServicesObjs = await emsClient.getTMSServices();
|
||||
|
||||
const fileLayers = fileLayerObjs.map(fileLayer => {
|
||||
//backfill to static settings
|
||||
const format = fileLayer.getDefaultFormatType();
|
||||
const meta = fileLayer.getDefaultFormatMeta();
|
||||
|
||||
return {
|
||||
name: fileLayer.getDisplayName(),
|
||||
origin: fileLayer.getOrigin(),
|
||||
id: fileLayer.getId(),
|
||||
created_at: fileLayer.getCreatedAt(),
|
||||
attribution: fileLayer.getHTMLAttribution(),
|
||||
attributions: fileLayer.getAttributions(),
|
||||
fields: fileLayer.getFieldsInLanguage(),
|
||||
// eslint-disable-next-line max-len
|
||||
url: useRelativePathToProxy ? `../${GIS_API_PATH}/${EMS_DATA_FILE_PATH}?id=${encodeURIComponent(fileLayer.getId())}` : fileLayer.getDefaultFormatUrl(),
|
||||
format: format, //legacy: format and meta are split up
|
||||
meta: meta, //legacy, format and meta are split up,
|
||||
emsLink: fileLayer.getEMSHotLink()
|
||||
};
|
||||
});
|
||||
|
||||
const tmsServices = tmsServicesObjs.map(tmsService => {
|
||||
return {
|
||||
origin: tmsService.getOrigin(),
|
||||
id: tmsService.getId(),
|
||||
minZoom: tmsService.getMinZoom(),
|
||||
maxZoom: tmsService.getMaxZoom(),
|
||||
attribution: tmsService.getHTMLAttribution(),
|
||||
attributionMarkdown: tmsService.getMarkdownAttribution(),
|
||||
// eslint-disable-next-line max-len
|
||||
url: useRelativePathToProxy ? `../${GIS_API_PATH}/${EMS_DATA_TMS_PATH}?id=${encodeURIComponent(tmsService.getId())}&x={x}&y={y}&z={z}` : tmsService.getUrlTemplate()
|
||||
};
|
||||
});
|
||||
|
||||
return { fileLayers, tmsServices };
|
||||
}
|
60
x-pack/plugins/maps/common/ems_util.test.js
Normal file
60
x-pack/plugins/maps/common/ems_util.test.js
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
|
||||
import {
|
||||
getEMSResources
|
||||
} from './ems_util';
|
||||
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import { getEMSClient } from 'ui/vis/__tests__/map/ems_client_util.js';
|
||||
|
||||
describe('ems util test', () => {
|
||||
|
||||
|
||||
it('Should get relative paths when using proxy', async () => {
|
||||
|
||||
const emsClient = getEMSClient({});
|
||||
const isEmsEnabled = true;
|
||||
const licenseId = 'foobar';
|
||||
const useProxy = true;
|
||||
const resources = await getEMSResources(emsClient, isEmsEnabled, licenseId, useProxy);
|
||||
|
||||
expect(resources.tmsServices[0].url.startsWith('../api/maps/ems/tms')).toBe(true);
|
||||
expect(resources.fileLayers[0].url.startsWith('../api/maps/ems/file')).toBe(true);
|
||||
expect(resources.fileLayers[1].url.startsWith('../api/maps/ems/file')).toBe(true);
|
||||
|
||||
});
|
||||
|
||||
|
||||
it('Should get absolute paths when not using proxy', async () => {
|
||||
|
||||
const emsClient = getEMSClient({});
|
||||
const isEmsEnabled = true;
|
||||
const licenseId = 'foobar';
|
||||
const useProxy = false;
|
||||
const resources = await getEMSResources(emsClient, isEmsEnabled, licenseId, useProxy);
|
||||
|
||||
expect(resources.tmsServices[0].url.startsWith('https://tiles-stage.elastic.co/')).toBe(true);
|
||||
expect(resources.fileLayers[0].url.startsWith('https://vector-staging.maps.elastic.co/files')).toBe(true);
|
||||
expect(resources.fileLayers[1].url.startsWith('https://vector-staging.maps.elastic.co/files')).toBe(true);
|
||||
});
|
||||
|
||||
it('Should get empty response when ems is disabled', async () => {
|
||||
|
||||
const emsClient = getEMSClient({});
|
||||
const isEmsEnabled = false;
|
||||
const licenseId = 'foobar';
|
||||
const useProxy = true;
|
||||
const resources = await getEMSResources(emsClient, isEmsEnabled, licenseId, !useProxy);
|
||||
|
||||
expect(resources.tmsServices.length).toBe(0);
|
||||
expect(resources.fileLayers.length).toBe(0);
|
||||
|
||||
});
|
||||
|
||||
|
||||
});
|
|
@ -18,6 +18,7 @@ import { initTelemetryCollection } from './server/maps_telemetry';
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { APP_ID, APP_ICON, createMapPath } from './common/constants';
|
||||
import { getAppTitle } from './common/i18n_getters';
|
||||
import _ from 'lodash';
|
||||
|
||||
export function maps(kibana) {
|
||||
|
||||
|
@ -39,9 +40,16 @@ export function maps(kibana) {
|
|||
injectDefaultVars(server) {
|
||||
const serverConfig = server.config();
|
||||
const mapConfig = serverConfig.get('map');
|
||||
|
||||
return {
|
||||
showMapsInspectorAdapter: serverConfig.get('xpack.maps.showMapsInspectorAdapter'),
|
||||
isEmsEnabled: mapConfig.includeElasticMapsService,
|
||||
proxyElasticMapsServiceInMaps: mapConfig.proxyElasticMapsServiceInMaps,
|
||||
emsManifestServiceUrl: mapConfig.manifestServiceUrl,
|
||||
emsLandingPageUrl: mapConfig.manifestServiceUrl,
|
||||
kbnPkgVersion: serverConfig.get('pkg.version'),
|
||||
regionmapLayers: _.get(mapConfig, 'regionmap.layers', []),
|
||||
tilemap: _.get(mapConfig, 'tilemap', [])
|
||||
};
|
||||
},
|
||||
embeddableFactories: [
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
import _ from 'lodash';
|
||||
import { KibanaTilemapSource } from '../shared/layers/sources/kibana_tilemap_source';
|
||||
import { EMSTMSSource } from '../shared/layers/sources/ems_tms_source';
|
||||
import { isMetaDataLoaded, getDataSourcesSync } from '../meta';
|
||||
import { isMetaDataLoaded, getEMSDataSourcesSync, getKibanaTileMap } from '../meta';
|
||||
import { DEFAULT_EMS_TILE_LAYER } from '../../common/constants';
|
||||
|
||||
export function getInitialLayers(savedMapLayerListJSON) {
|
||||
|
@ -15,6 +15,16 @@ export function getInitialLayers(savedMapLayerListJSON) {
|
|||
return JSON.parse(savedMapLayerListJSON);
|
||||
}
|
||||
|
||||
const tilemapSourceFromKibana = getKibanaTileMap();
|
||||
if (_.get(tilemapSourceFromKibana, 'url')) {
|
||||
const sourceDescriptor = KibanaTilemapSource.createDescriptor();
|
||||
const source = new KibanaTilemapSource(sourceDescriptor);
|
||||
const layer = source.createDefaultLayer();
|
||||
return [
|
||||
layer.toLayerDescriptor()
|
||||
];
|
||||
}
|
||||
|
||||
if (!isMetaDataLoaded()) {
|
||||
const descriptor = EMSTMSSource.createDescriptor(DEFAULT_EMS_TILE_LAYER);
|
||||
const source = new EMSTMSSource(descriptor);
|
||||
|
@ -24,17 +34,8 @@ export function getInitialLayers(savedMapLayerListJSON) {
|
|||
];
|
||||
}
|
||||
|
||||
const dataSources = getDataSourcesSync();
|
||||
if (_.get(dataSources, 'kibana.tilemap.url')) {
|
||||
const sourceDescriptor = KibanaTilemapSource.createDescriptor();
|
||||
const source = new KibanaTilemapSource(sourceDescriptor);
|
||||
const layer = source.createDefaultLayer();
|
||||
return [
|
||||
layer.toLayerDescriptor()
|
||||
];
|
||||
}
|
||||
|
||||
const emsTmsServices = _.get(dataSources, 'ems.tms');
|
||||
const emsDataSources = getEMSDataSourcesSync();
|
||||
const emsTmsServices = _.get(emsDataSources, 'ems.tms');
|
||||
if (emsTmsServices && emsTmsServices.length > 0) {
|
||||
const sourceDescriptor = EMSTMSSource.createDescriptor(emsTmsServices[0].id);
|
||||
const source = new EMSTMSSource(sourceDescriptor, { emsTmsServices });
|
||||
|
|
|
@ -47,12 +47,15 @@ describe('Saved object does not have layer list', () => {
|
|||
});
|
||||
|
||||
function mockDataSourceResponse(dataSources) {
|
||||
require('../meta').getDataSourcesSync = () => {
|
||||
require('../meta').getEMSDataSourcesSync = () => {
|
||||
return dataSources;
|
||||
};
|
||||
require('../meta').isMetaDataLoaded = () => {
|
||||
return true;
|
||||
};
|
||||
require('../meta').getKibanaTileMap = () => {
|
||||
return null;
|
||||
};
|
||||
}
|
||||
|
||||
it('should get the default EMS layer when metadata has not loaded yet', () => {
|
||||
|
@ -86,9 +89,11 @@ describe('Saved object does not have layer list', () => {
|
|||
it('Should get initial layer from Kibana tilemap data source when Kibana tilemap is configured ', () => {
|
||||
|
||||
mockDataSourceResponse({
|
||||
kibana: mockKibanaDataSource,
|
||||
ems: mockEmsDataSource
|
||||
});
|
||||
require('../meta').getKibanaTileMap = () => {
|
||||
return mockKibanaDataSource.tilemap;
|
||||
};
|
||||
|
||||
const layers = getInitialLayers(null);
|
||||
expect(layers).toEqual([{
|
||||
|
|
|
@ -8,10 +8,12 @@ import { uiModules } from 'ui/modules';
|
|||
import { SearchSourceProvider } from 'ui/courier';
|
||||
import { FilterBarQueryFilterProvider } from 'ui/filter_bar/query_filter';
|
||||
import { getRequestInspectorStats, getResponseInspectorStats } from 'ui/courier/utils/courier_inspector_utils';
|
||||
import { XPackInfoProvider } from 'plugins/xpack_main/services/xpack_info';
|
||||
|
||||
export let indexPatternService;
|
||||
export let SearchSource;
|
||||
export let filterBarQueryFilter;
|
||||
export let xpackInfo;
|
||||
|
||||
export async function fetchSearchSourceAndRecordWithInspector({ searchSource, requestId, requestName, requestDesc, inspectorAdapters }) {
|
||||
const inspectorRequest = inspectorAdapters.requests.start(
|
||||
|
@ -40,4 +42,5 @@ uiModules.get('app/maps').run(($injector) => {
|
|||
const Private = $injector.get('Private');
|
||||
SearchSource = Private(SearchSourceProvider);
|
||||
filterBarQueryFilter = Private(FilterBarQueryFilterProvider);
|
||||
xpackInfo = Private(XPackInfoProvider);
|
||||
});
|
||||
|
|
|
@ -5,17 +5,23 @@
|
|||
*/
|
||||
|
||||
|
||||
import { GIS_API_PATH } from '../common/constants';
|
||||
import { GIS_API_PATH, EMS_META_PATH } from '../common/constants';
|
||||
import _ from 'lodash';
|
||||
import { getEMSResources } from '../common/ems_util';
|
||||
import chrome from 'ui/chrome';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { EMSClient } from 'ui/vis/map/ems_client';
|
||||
import { xpackInfo } from './kibana_services';
|
||||
|
||||
const GIS_API_RELATIVE = `../${GIS_API_PATH}`;
|
||||
|
||||
let meta = null;
|
||||
let emsSources = null;
|
||||
let loadingMetaPromise = null;
|
||||
let isLoaded = false;
|
||||
export async function getDataSources() {
|
||||
if (meta) {
|
||||
return meta;
|
||||
|
||||
export async function getEMSDataSources() {
|
||||
if (emsSources) {
|
||||
return emsSources;
|
||||
}
|
||||
|
||||
if (loadingMetaPromise) {
|
||||
|
@ -24,12 +30,32 @@ export async function getDataSources() {
|
|||
|
||||
loadingMetaPromise = new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
const response = await fetch(`${GIS_API_RELATIVE}/meta`);
|
||||
const metaJson = await response.json();
|
||||
const proxyElasticMapsServiceInMaps = chrome.getInjected('proxyElasticMapsServiceInMaps', false);
|
||||
if (proxyElasticMapsServiceInMaps) {
|
||||
const fullResponse = await fetch(`${GIS_API_RELATIVE}/${EMS_META_PATH}`);
|
||||
emsSources = await fullResponse.json();
|
||||
} else {
|
||||
const emsClient = new EMSClient({
|
||||
language: i18n.getLocale(),
|
||||
kbnVersion: chrome.getInjected('kbnPkgVersion'),
|
||||
manifestServiceUrl: chrome.getInjected('emsManifestServiceUrl'),
|
||||
landingPageUrl: chrome.getInjected('emsLandingPageUrl')
|
||||
});
|
||||
const isEmsEnabled = chrome.getInjected('isEmsEnabled', true);
|
||||
const xpackMapsFeature = xpackInfo.get('features.maps');
|
||||
const licenseId = xpackMapsFeature && xpackMapsFeature.maps && xpackMapsFeature.uid ? xpackMapsFeature.uid : '';
|
||||
|
||||
const emsResponse = await getEMSResources(emsClient, isEmsEnabled, licenseId, false);
|
||||
emsSources = {
|
||||
ems: {
|
||||
file: emsResponse.fileLayers,
|
||||
tms: emsResponse.tmsServices
|
||||
}
|
||||
};
|
||||
}
|
||||
isLoaded = true;
|
||||
meta = metaJson.data_sources;
|
||||
resolve(meta);
|
||||
} catch(e) {
|
||||
resolve(emsSources);
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
});
|
||||
|
@ -39,8 +65,8 @@ export async function getDataSources() {
|
|||
/**
|
||||
* Should only call this after verifying `isMetadataLoaded` equals true
|
||||
*/
|
||||
export function getDataSourcesSync() {
|
||||
return meta;
|
||||
export function getEMSDataSourcesSync() {
|
||||
return emsSources;
|
||||
}
|
||||
|
||||
export function isMetaDataLoaded() {
|
||||
|
@ -48,21 +74,19 @@ export function isMetaDataLoaded() {
|
|||
}
|
||||
|
||||
export async function getEmsVectorFilesMeta() {
|
||||
const dataSource = await getDataSources();
|
||||
const dataSource = await getEMSDataSources();
|
||||
return _.get(dataSource, 'ems.file', []);
|
||||
}
|
||||
|
||||
export async function getEmsTMSServices() {
|
||||
const dataSource = await getDataSources();
|
||||
const dataSource = await getEMSDataSources();
|
||||
return _.get(dataSource, 'ems.tms', []);
|
||||
}
|
||||
|
||||
export async function getKibanaRegionList() {
|
||||
const dataSource = await getDataSources();
|
||||
return _.get(dataSource, 'kibana.regionmap', []);
|
||||
export function getKibanaRegionList() {
|
||||
return chrome.getInjected('regionmapLayers');
|
||||
}
|
||||
|
||||
export async function getKibanaTileMap() {
|
||||
const dataSource = await getDataSources();
|
||||
return _.get(dataSource, 'kibana.tilemap', {});
|
||||
export function getKibanaTileMap() {
|
||||
return chrome.getInjected('tilemap');
|
||||
}
|
||||
|
|
64
x-pack/plugins/maps/public/meta.test.js
Normal file
64
x-pack/plugins/maps/public/meta.test.js
Normal file
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import {
|
||||
getEMSDataSources
|
||||
} from './meta';
|
||||
|
||||
|
||||
jest.mock('ui/chrome',
|
||||
() => ({
|
||||
getBasePath: () => {
|
||||
return '<basepath>';
|
||||
},
|
||||
getInjected(key) {
|
||||
if (key === 'proxyElasticMapsServiceInMaps') {
|
||||
return false;
|
||||
} else if (key === 'isEmsEnabled') {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
getUiSettingsClient: () => {
|
||||
return {
|
||||
get: () => {
|
||||
return '';
|
||||
}
|
||||
};
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
jest.mock('ui/vis/map/ems_client', () => {
|
||||
const module = require('ui/vis/__tests__/map/ems_client_util.js');
|
||||
function EMSClient() {
|
||||
return module.getEMSClient();
|
||||
}
|
||||
return {
|
||||
EMSClient: EMSClient
|
||||
};
|
||||
});
|
||||
|
||||
jest.mock('./kibana_services', () => {
|
||||
return {
|
||||
xpackInfo: {
|
||||
get() {
|
||||
return 'foobarlicenseid';
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
describe('default use without proxy', () => {
|
||||
|
||||
it('should return absolute urls', async () => {
|
||||
|
||||
|
||||
const resources = await getEMSDataSources();
|
||||
expect(resources.ems.tms[0].url.startsWith('https://tiles-stage.elastic.co/')).toBe(true);
|
||||
expect(resources.ems.file[0].url.startsWith('https://vector-staging.maps.elastic.co/files')).toBe(true);
|
||||
expect(resources.ems.file[1].url.startsWith('https://vector-staging.maps.elastic.co/files')).toBe(true);
|
||||
});
|
||||
});
|
|
@ -7,7 +7,7 @@
|
|||
import { AbstractVectorSource } from '../vector_source';
|
||||
import { VECTOR_SHAPE_TYPES } from '../vector_feature_types';
|
||||
import React from 'react';
|
||||
import { GIS_API_PATH, EMS_FILE } from '../../../../../common/constants';
|
||||
import { EMS_FILE } from '../../../../../common/constants';
|
||||
import { getEmsVectorFilesMeta } from '../../../../meta';
|
||||
import { EMSFileCreateSourceEditor } from './create_source_editor';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
@ -59,7 +59,7 @@ export class EMSFileSource extends AbstractVectorSource {
|
|||
const featureCollection = await AbstractVectorSource.getGeoJson({
|
||||
format: emsVectorFileMeta.format,
|
||||
featureCollectionPath: 'data',
|
||||
fetchUrl: `../${GIS_API_PATH}/data/ems?id=${encodeURIComponent(this._descriptor.id)}`
|
||||
fetchUrl: emsVectorFileMeta.url
|
||||
});
|
||||
return {
|
||||
data: featureCollection,
|
||||
|
|
|
@ -20,7 +20,7 @@ export class CreateSourceEditor extends React.Component {
|
|||
}
|
||||
|
||||
_loadList = async () => {
|
||||
const list = await getKibanaRegionList();
|
||||
const list = getKibanaRegionList();
|
||||
if (this._isMounted) {
|
||||
this.setState({
|
||||
regionmapLayers: list
|
||||
|
|
|
@ -59,7 +59,7 @@ export class KibanaRegionmapSource extends AbstractVectorSource {
|
|||
}
|
||||
|
||||
async _getVectorFileMeta() {
|
||||
const regionList = await getKibanaRegionList();
|
||||
const regionList = getKibanaRegionList();
|
||||
const meta = regionList.find(source => source.name === this._descriptor.name);
|
||||
if (!meta) {
|
||||
throw new Error(i18n.translate('xpack.maps.source.kbnRegionMap.noConfigErrorMessage', {
|
||||
|
|
|
@ -21,7 +21,7 @@ export class CreateSourceEditor extends Component {
|
|||
};
|
||||
|
||||
_loadUrl = async () => {
|
||||
const tilemap = await getKibanaTileMap();
|
||||
const tilemap = getKibanaTileMap();
|
||||
if (this._isMounted) {
|
||||
this.setState(
|
||||
{ url: tilemap.url },
|
||||
|
|
|
@ -68,7 +68,7 @@ export class KibanaTilemapSource extends AbstractTMSSource {
|
|||
}
|
||||
|
||||
async getUrlTemplate() {
|
||||
const tilemap = await getKibanaTileMap();
|
||||
const tilemap = getKibanaTileMap();
|
||||
if (!tilemap.url) {
|
||||
throw new Error(i18n.translate('xpack.maps.source.kbnTMS.noConfigErrorMessage', {
|
||||
defaultMessage: `Unable to find map.tilemap.url configuration in the kibana.yml`
|
||||
|
|
|
@ -5,10 +5,11 @@
|
|||
*/
|
||||
|
||||
|
||||
import { GIS_API_PATH } from '../common/constants';
|
||||
import { EMS_DATA_FILE_PATH, EMS_DATA_TMS_PATH, EMS_META_PATH, GIS_API_PATH } from '../common/constants';
|
||||
import fetch from 'node-fetch';
|
||||
import _ from 'lodash';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { getEMSResources } from '../common/ems_util';
|
||||
import Boom from 'boom';
|
||||
|
||||
const ROOT = `/${GIS_API_PATH}`;
|
||||
|
||||
|
@ -26,37 +27,99 @@ export function initRoutes(server, licenseUid) {
|
|||
|
||||
server.route({
|
||||
method: 'GET',
|
||||
path: `${ROOT}/data/ems`,
|
||||
path: `${ROOT}/${EMS_DATA_FILE_PATH}`,
|
||||
handler: async (request) => {
|
||||
|
||||
if (!mapConfig.proxyElasticMapsServiceInMaps) {
|
||||
server.log('warning', `Cannot load content from EMS when map.proxyElasticMapsServiceInMaps is turned off`);
|
||||
throw Boom.notFound();
|
||||
}
|
||||
|
||||
if (!request.query.id) {
|
||||
server.log('warning', 'Must supply id parameters to retrieve EMS file');
|
||||
return null;
|
||||
}
|
||||
|
||||
const ems = await getEMSResources(licenseUid);
|
||||
|
||||
const ems = await getEMSResources(emsClient, mapConfig.includeElasticMapsService, licenseUid, false);
|
||||
const layer = ems.fileLayers.find(layer => layer.id === request.query.id);
|
||||
if (!layer) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const file = await fetch(layer.url);
|
||||
return await file.json();
|
||||
try {
|
||||
const file = await fetch(layer.url);
|
||||
return await file.json();
|
||||
} catch(e) {
|
||||
server.log('warning', `Cannot connect to EMS for file, error: ${e.message}`);
|
||||
throw Boom.badRequest(`Cannot connect to EMS`);
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
server.route({
|
||||
method: 'GET',
|
||||
path: `${ROOT}/${EMS_DATA_TMS_PATH}`,
|
||||
handler: async (request, h) => {
|
||||
|
||||
if (!mapConfig.proxyElasticMapsServiceInMaps) {
|
||||
server.log('warning', `Cannot load content from EMS when map.proxyElasticMapsServiceInMaps is turned off`);
|
||||
throw Boom.notFound();
|
||||
}
|
||||
|
||||
if (!request.query.id ||
|
||||
typeof parseInt(request.query.x, 10) !== 'number' ||
|
||||
typeof parseInt(request.query.y, 10) !== 'number' ||
|
||||
typeof parseInt(request.query.z, 10) !== 'number'
|
||||
) {
|
||||
server.log('warning', 'Must supply id/x/y/z parameters to retrieve EMS tile');
|
||||
return null;
|
||||
}
|
||||
|
||||
const ems = await getEMSResources(emsClient, mapConfig.includeElasticMapsService, licenseUid, false);
|
||||
const tmsService = ems.tmsServices.find(layer => layer.id === request.query.id);
|
||||
if (!tmsService) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const url = tmsService.url
|
||||
.replace('{x}', request.query.x)
|
||||
.replace('{y}', request.query.y)
|
||||
.replace('{z}', request.query.z);
|
||||
|
||||
try {
|
||||
const tile = await fetch(url);
|
||||
const arrayBuffer = await tile.arrayBuffer();
|
||||
const buffer = Buffer.from(arrayBuffer);
|
||||
let response = h.response(buffer);
|
||||
response = response.bytes(buffer.length);
|
||||
response = response.header('Content-Disposition', 'inline');
|
||||
response = response.header('Content-type', 'image/png');
|
||||
response = response.encoding('binary');
|
||||
return response;
|
||||
} catch(e) {
|
||||
server.log('warning', `Cannot connect to EMS for tile, error: ${e.message}`);
|
||||
throw Boom.badRequest(`Cannot connect to EMS`);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: 'GET',
|
||||
path: `${ROOT}/meta`,
|
||||
path: `${ROOT}/${EMS_META_PATH}`,
|
||||
handler: async () => {
|
||||
|
||||
if (!mapConfig.proxyElasticMapsServiceInMaps) {
|
||||
server.log('warning', `Cannot load content from EMS when map.proxyElasticMapsServiceInMaps is turned off`);
|
||||
throw Boom.notFound();
|
||||
}
|
||||
|
||||
let ems;
|
||||
try {
|
||||
ems = await getEMSResources(licenseUid);
|
||||
ems = await getEMSResources(emsClient, mapConfig.includeElasticMapsService, licenseUid, true);
|
||||
} catch (e) {
|
||||
server.log('warning', `Cannot connect to EMS, error: ${e}`);
|
||||
server.log('warning', `Cannot connect to EMS, error: ${e.message}`);
|
||||
ems = {
|
||||
fileLayers: [],
|
||||
tmsServices: []
|
||||
|
@ -64,15 +127,9 @@ export function initRoutes(server, licenseUid) {
|
|||
}
|
||||
|
||||
return ({
|
||||
data_sources: {
|
||||
ems: {
|
||||
file: ems.fileLayers,
|
||||
tms: ems.tmsServices
|
||||
},
|
||||
kibana: {
|
||||
regionmap: _.get(mapConfig, 'regionmap.layers', []),
|
||||
tilemap: _.get(mapConfig, 'tilemap', [])
|
||||
}
|
||||
ems: {
|
||||
file: ems.fileLayers,
|
||||
tms: ems.tmsServices
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -93,57 +150,9 @@ export function initRoutes(server, licenseUid) {
|
|||
try {
|
||||
const { count } = await callWithRequest(request, 'count', { index: query.index });
|
||||
return { count };
|
||||
} catch(error) {
|
||||
} catch (error) {
|
||||
return h.response().code(400);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
async function getEMSResources(licenseUid) {
|
||||
|
||||
if (!mapConfig.includeElasticMapsService) {
|
||||
return {
|
||||
fileLayers: [],
|
||||
tmsServices: []
|
||||
};
|
||||
}
|
||||
|
||||
emsClient.addQueryParams({ license: licenseUid });
|
||||
const fileLayerObjs = await emsClient.getFileLayers();
|
||||
const tmsServicesObjs = await emsClient.getTMSServices();
|
||||
|
||||
const fileLayers = fileLayerObjs.map(fileLayer => {
|
||||
//backfill to static settings
|
||||
const format = fileLayer.getDefaultFormatType();
|
||||
const meta = fileLayer.getDefaultFormatMeta();
|
||||
|
||||
return {
|
||||
name: fileLayer.getDisplayName(),
|
||||
origin: fileLayer.getOrigin(),
|
||||
id: fileLayer.getId(),
|
||||
created_at: fileLayer.getCreatedAt(),
|
||||
attribution: fileLayer.getHTMLAttribution(),
|
||||
attributions: fileLayer.getAttributions(),
|
||||
fields: fileLayer.getFieldsInLanguage(),
|
||||
url: fileLayer.getDefaultFormatUrl(),
|
||||
format: format, //legacy: format and meta are split up
|
||||
meta: meta, //legacy, format and meta are split up,
|
||||
emsLink: fileLayer.getEMSHotLink()
|
||||
};
|
||||
});
|
||||
|
||||
const tmsServices = tmsServicesObjs.map(tmsService => {
|
||||
return {
|
||||
origin: tmsService.getOrigin(),
|
||||
id: tmsService.getId(),
|
||||
minZoom: tmsService.getMinZoom(),
|
||||
maxZoom: tmsService.getMaxZoom(),
|
||||
attribution: tmsService.getHTMLAttribution(),
|
||||
attributionMarkdown: tmsService.getMarkdownAttribution(),
|
||||
url: tmsService.getUrlTemplate()
|
||||
};
|
||||
});
|
||||
|
||||
return { fileLayers, tmsServices };
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue