Skip to content

Commit 031c902

Browse files
Merge branch 'master' into alerts/fix-buggy-default-message
2 parents c967f84 + 4546352 commit 031c902

File tree

76 files changed

+8360
-389
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+8360
-389
lines changed

docs/developer/plugin/migrating-legacy-plugins-examples.asciidoc

+3-2
Original file line numberDiff line numberDiff line change
@@ -902,8 +902,9 @@ The most significant changes on the Kibana side for the consumers are the follow
902902
===== User client accessor
903903
Internal /current user client accessors has been renamed and are now
904904
properties instead of functions:
905-
** `callAsInternalUser('ping')` -> `asInternalUser.ping()`
906-
** `callAsCurrentUser('ping')` -> `asCurrentUser.ping()`
905+
906+
* `callAsInternalUser('ping')` -> `asInternalUser.ping()`
907+
* `callAsCurrentUser('ping')` -> `asCurrentUser.ping()`
907908
* the API now reflects the `Client`’s instead of leveraging the
908909
string-based endpoint names the `LegacyAPICaller` was using.
909910

src/plugins/discover/public/application/angular/discover.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,8 @@ function discoverController($element, $route, $scope, $timeout, $window, Promise
252252
if (!_.isEqual(newStatePartial, oldStatePartial)) {
253253
$scope.$evalAsync(async () => {
254254
if (oldStatePartial.index !== newStatePartial.index) {
255-
//in case of index switch the route has currently to be reloaded, legacy
255+
//in case of index pattern switch the route has currently to be reloaded, legacy
256+
$route.reload();
256257
return;
257258
}
258259

@@ -289,8 +290,7 @@ function discoverController($element, $route, $scope, $timeout, $window, Promise
289290
$scope.state.sort,
290291
config.get(MODIFY_COLUMNS_ON_SWITCH)
291292
);
292-
await replaceUrlAppState(nextAppState);
293-
$route.reload();
293+
await setAppState(nextAppState);
294294
}
295295
};
296296

src/plugins/kibana_usage_collection/server/collectors/application_usage/schema.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ export const applicationUsageSchema = {
7373
logs: commonSchema,
7474
metrics: commonSchema,
7575
infra: commonSchema, // It's a forward app so we'll likely never report it
76-
ingestManager: commonSchema,
76+
fleet: commonSchema,
7777
lens: commonSchema,
7878
maps: commonSchema,
7979
ml: commonSchema,

src/plugins/share/server/routes/lib/short_url_assert_valid.test.ts

+24-21
Original file line numberDiff line numberDiff line change
@@ -19,36 +19,39 @@
1919

2020
import { shortUrlAssertValid } from './short_url_assert_valid';
2121

22+
const PROTOCOL_ERROR = /^Short url targets cannot have a protocol/;
23+
const HOSTNAME_ERROR = /^Short url targets cannot have a hostname/;
24+
const PATH_ERROR = /^Short url target path must be in the format/;
25+
2226
describe('shortUrlAssertValid()', () => {
2327
const invalid = [
24-
['protocol', 'http://localhost:5601/app/kibana'],
25-
['protocol', 'https://localhost:5601/app/kibana'],
26-
['protocol', 'mailto:foo@bar.net'],
27-
['protocol', 'javascript:alert("hi")'], // eslint-disable-line no-script-url
28-
['hostname', 'localhost/app/kibana'],
29-
['hostname and port', 'local.host:5601/app/kibana'],
30-
['hostname and auth', 'user:pass@localhost.net/app/kibana'],
31-
['path traversal', '/app/../../not-kibana'],
32-
['deep path', '/app/kibana/foo'],
33-
['deep path', '/app/kibana/foo/bar'],
34-
['base path', '/base/app/kibana'],
28+
['protocol', 'http://localhost:5601/app/kibana', PROTOCOL_ERROR],
29+
['protocol', 'https://localhost:5601/app/kibana', PROTOCOL_ERROR],
30+
['protocol', 'mailto:foo@bar.net', PROTOCOL_ERROR],
31+
['protocol', 'javascript:alert("hi")', PROTOCOL_ERROR], // eslint-disable-line no-script-url
32+
['hostname', 'localhost/app/kibana', PATH_ERROR], // according to spec, this is not a valid URL -- you cannot specify a hostname without a protocol
33+
['hostname and port', 'local.host:5601/app/kibana', PROTOCOL_ERROR], // parser detects 'local.host' as the protocol
34+
['hostname and auth', 'user:pass@localhost.net/app/kibana', PROTOCOL_ERROR], // parser detects 'user' as the protocol
35+
['path traversal', '/app/../../not-kibana', PATH_ERROR], // fails because there are >2 path parts
36+
['path traversal', '/../not-kibana', PATH_ERROR], // fails because first path part is not 'app'
37+
['deep path', '/app/kibana/foo', PATH_ERROR], // fails because there are >2 path parts
38+
['deeper path', '/app/kibana/foo/bar', PATH_ERROR], // fails because there are >2 path parts
39+
['base path', '/base/app/kibana', PATH_ERROR], // fails because there are >2 path parts
40+
['path with an extra leading slash', '//foo/app/kibana', HOSTNAME_ERROR], // parser detects 'foo' as the hostname
41+
['path with an extra leading slash', '///app/kibana', HOSTNAME_ERROR], // parser detects '' as the hostname
42+
['path without app', '/foo/kibana', PATH_ERROR], // fails because first path part is not 'app'
43+
['path without appId', '/app/', PATH_ERROR], // fails because there is only one path part (leading and trailing slashes are trimmed)
3544
];
3645

37-
invalid.forEach(([desc, url]) => {
38-
it(`fails when url has ${desc}`, () => {
39-
try {
40-
shortUrlAssertValid(url);
41-
throw new Error(`expected assertion to throw`);
42-
} catch (err) {
43-
if (!err || !err.isBoom) {
44-
throw err;
45-
}
46-
}
46+
invalid.forEach(([desc, url, error]) => {
47+
it(`fails when url has ${desc as string}`, () => {
48+
expect(() => shortUrlAssertValid(url as string)).toThrowError(error);
4749
});
4850
});
4951

5052
const valid = [
5153
'/app/kibana',
54+
'/app/kibana/', // leading and trailing slashes are trimmed
5255
'/app/monitoring#angular/route',
5356
'/app/text#document-id',
5457
'/app/some?with=query',

src/plugins/share/server/routes/lib/short_url_assert_valid.ts

+8-4
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,22 @@ import { trim } from 'lodash';
2222
import Boom from '@hapi/boom';
2323

2424
export function shortUrlAssertValid(url: string) {
25-
const { protocol, hostname, pathname } = parse(url);
25+
const { protocol, hostname, pathname } = parse(
26+
url,
27+
false /* parseQueryString */,
28+
true /* slashesDenoteHost */
29+
);
2630

27-
if (protocol) {
31+
if (protocol !== null) {
2832
throw Boom.notAcceptable(`Short url targets cannot have a protocol, found "${protocol}"`);
2933
}
3034

31-
if (hostname) {
35+
if (hostname !== null) {
3236
throw Boom.notAcceptable(`Short url targets cannot have a hostname, found "${hostname}"`);
3337
}
3438

3539
const pathnameParts = trim(pathname === null ? undefined : pathname, '/').split('/');
36-
if (pathnameParts.length !== 2) {
40+
if (pathnameParts.length !== 2 || pathnameParts[0] !== 'app' || !pathnameParts[1]) {
3741
throw Boom.notAcceptable(
3842
`Short url target path must be in the format "/app/{{appId}}", found "${pathname}"`
3943
);

src/plugins/telemetry/schema/oss_plugins.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -616,7 +616,7 @@
616616
}
617617
}
618618
},
619-
"ingestManager": {
619+
"fleet": {
620620
"properties": {
621621
"clicks_total": {
622622
"type": "long"

src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/time_shift.js

+7-5
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
* under the License.
1818
*/
1919

20-
import _ from 'lodash';
20+
import { startsWith } from 'lodash';
2121
import moment from 'moment';
2222

2323
export function timeShift(resp, panel, series) {
@@ -26,13 +26,15 @@ export function timeShift(resp, panel, series) {
2626
const matches = series.offset_time.match(/^([+-]?[\d]+)([shmdwMy]|ms)$/);
2727

2828
if (matches) {
29-
const offsetValue = Number(matches[1]);
29+
const offsetValue = matches[1];
3030
const offsetUnit = matches[2];
31-
const offset = moment.duration(offsetValue, offsetUnit).valueOf();
3231

3332
results.forEach((item) => {
34-
if (_.startsWith(item.id, series.id)) {
35-
item.data = item.data.map(([time, value]) => [time + offset, value]);
33+
if (startsWith(item.id, series.id)) {
34+
item.data = item.data.map((row) => [
35+
moment.utc(row[0]).add(offsetValue, offsetUnit).valueOf(),
36+
row[1],
37+
]);
3638
}
3739
});
3840
}

test/api_integration/apis/saved_objects/migrations.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ function getLogMock() {
5454
export default ({ getService }: FtrProviderContext) => {
5555
const esClient = getService('es');
5656

57-
describe('Kibana index migration', () => {
57+
// FLAKY: https://github.com/elastic/kibana/issues/84445
58+
describe.skip('Kibana index migration', () => {
5859
before(() => esClient.indices.delete({ index: '.migrate-*' }));
5960

6061
it('Migrates an existing index that has never been migrated before', async () => {

test/functional/apps/discover/_indexpattern_without_timefield.ts

+17
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import { FtrProviderContext } from '../../ftr_provider_context';
2121

2222
export default function ({ getService, getPageObjects }: FtrProviderContext) {
23+
const browser = getService('browser');
2324
const esArchiver = getService('esArchiver');
2425
const kibanaServer = getService('kibanaServer');
2526
const security = getService('security');
@@ -50,5 +51,21 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
5051
throw new Error('Expected timepicker to exist');
5152
}
5253
});
54+
it('should switch between with and without timefield using the browser back button', async () => {
55+
await PageObjects.discover.selectIndexPattern('without-timefield');
56+
if (await PageObjects.timePicker.timePickerExists()) {
57+
throw new Error('Expected timepicker not to exist');
58+
}
59+
60+
await PageObjects.discover.selectIndexPattern('with-timefield');
61+
if (!(await PageObjects.timePicker.timePickerExists())) {
62+
throw new Error('Expected timepicker to exist');
63+
}
64+
// Navigating back to discover
65+
await browser.goBack();
66+
if (await PageObjects.timePicker.timePickerExists()) {
67+
throw new Error('Expected timepicker not to exist');
68+
}
69+
});
5370
});
5471
}

x-pack/plugins/alerts/public/alert_api.test.ts

+1-65
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
import { AlertType } from '../common';
88
import { httpServiceMock } from '../../../../src/core/public/mocks';
9-
import { loadAlert, loadAlertState, loadAlertType, loadAlertTypes } from './alert_api';
9+
import { loadAlert, loadAlertType, loadAlertTypes } from './alert_api';
1010
import uuid from 'uuid';
1111

1212
const http = httpServiceMock.createStartContract();
@@ -114,67 +114,3 @@ describe('loadAlert', () => {
114114
expect(http.get).toHaveBeenCalledWith(`/api/alerts/alert/${alertId}`);
115115
});
116116
});
117-
118-
describe('loadAlertState', () => {
119-
test('should call get API with base parameters', async () => {
120-
const alertId = uuid.v4();
121-
const resolvedValue = {
122-
alertTypeState: {
123-
some: 'value',
124-
},
125-
alertInstances: {
126-
first_instance: {},
127-
second_instance: {},
128-
},
129-
};
130-
http.get.mockResolvedValueOnce(resolvedValue);
131-
132-
expect(await loadAlertState({ http, alertId })).toEqual(resolvedValue);
133-
expect(http.get).toHaveBeenCalledWith(`/api/alerts/alert/${alertId}/state`);
134-
});
135-
136-
test('should parse AlertInstances', async () => {
137-
const alertId = uuid.v4();
138-
const resolvedValue = {
139-
alertTypeState: {
140-
some: 'value',
141-
},
142-
alertInstances: {
143-
first_instance: {
144-
state: {},
145-
meta: {
146-
lastScheduledActions: {
147-
group: 'first_group',
148-
date: '2020-02-09T23:15:41.941Z',
149-
},
150-
},
151-
},
152-
},
153-
};
154-
http.get.mockResolvedValueOnce(resolvedValue);
155-
156-
expect(await loadAlertState({ http, alertId })).toEqual({
157-
...resolvedValue,
158-
alertInstances: {
159-
first_instance: {
160-
state: {},
161-
meta: {
162-
lastScheduledActions: {
163-
group: 'first_group',
164-
date: new Date('2020-02-09T23:15:41.941Z'),
165-
},
166-
},
167-
},
168-
},
169-
});
170-
expect(http.get).toHaveBeenCalledWith(`/api/alerts/alert/${alertId}/state`);
171-
});
172-
173-
test('should handle empty response from api', async () => {
174-
const alertId = uuid.v4();
175-
http.get.mockResolvedValueOnce('');
176-
177-
expect(await loadAlertState({ http, alertId })).toEqual({});
178-
expect(http.get).toHaveBeenCalledWith(`/api/alerts/alert/${alertId}/state`);
179-
});
180-
});

x-pack/plugins/alerts/public/alert_api.ts

+7-34
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,9 @@
55
*/
66

77
import { HttpSetup } from 'kibana/public';
8-
import * as t from 'io-ts';
9-
import { pipe } from 'fp-ts/lib/pipeable';
10-
import { fold } from 'fp-ts/lib/Either';
11-
import { findFirst } from 'fp-ts/lib/Array';
12-
import { isNone } from 'fp-ts/lib/Option';
13-
148
import { i18n } from '@kbn/i18n';
15-
import { BASE_ALERT_API_PATH, alertStateSchema } from '../common';
16-
import { Alert, AlertType, AlertTaskState } from '../common';
9+
import { BASE_ALERT_API_PATH } from '../common';
10+
import type { Alert, AlertType } from '../common';
1711

1812
export async function loadAlertTypes({ http }: { http: HttpSetup }): Promise<AlertType[]> {
1913
return await http.get(`${BASE_ALERT_API_PATH}/list_alert_types`);
@@ -26,10 +20,10 @@ export async function loadAlertType({
2620
http: HttpSetup;
2721
id: AlertType['id'];
2822
}): Promise<AlertType> {
29-
const maybeAlertType = findFirst<AlertType>((type) => type.id === id)(
30-
await http.get(`${BASE_ALERT_API_PATH}/list_alert_types`)
31-
);
32-
if (isNone(maybeAlertType)) {
23+
const maybeAlertType = ((await http.get(
24+
`${BASE_ALERT_API_PATH}/list_alert_types`
25+
)) as AlertType[]).find((type) => type.id === id);
26+
if (!maybeAlertType) {
3327
throw new Error(
3428
i18n.translate('xpack.alerts.loadAlertType.missingAlertTypeError', {
3529
defaultMessage: 'Alert type "{id}" is not registered.',
@@ -39,7 +33,7 @@ export async function loadAlertType({
3933
})
4034
);
4135
}
42-
return maybeAlertType.value;
36+
return maybeAlertType;
4337
}
4438

4539
export async function loadAlert({
@@ -51,24 +45,3 @@ export async function loadAlert({
5145
}): Promise<Alert> {
5246
return await http.get(`${BASE_ALERT_API_PATH}/alert/${alertId}`);
5347
}
54-
55-
type EmptyHttpResponse = '';
56-
export async function loadAlertState({
57-
http,
58-
alertId,
59-
}: {
60-
http: HttpSetup;
61-
alertId: string;
62-
}): Promise<AlertTaskState> {
63-
return await http
64-
.get(`${BASE_ALERT_API_PATH}/alert/${alertId}/state`)
65-
.then((state: AlertTaskState | EmptyHttpResponse) => (state ? state : {}))
66-
.then((state: AlertTaskState) => {
67-
return pipe(
68-
alertStateSchema.decode(state),
69-
fold((e: t.Errors) => {
70-
throw new Error(`Alert "${alertId}" has invalid state`);
71-
}, t.identity)
72-
);
73-
});
74-
}

x-pack/plugins/apm/public/components/app/service_node_metrics/index.tsx

+5-20
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,11 @@ export function ServiceNodeMetrics({ match }: ServiceNodeMetricsProps) {
5959
const { urlParams, uiFilters } = useUrlParams();
6060
const { serviceName, serviceNodeName } = match.params;
6161
const { agentName } = useAgentName();
62-
const { data } = useServiceMetricCharts(urlParams, agentName);
62+
const { data } = useServiceMetricCharts(
63+
urlParams,
64+
agentName,
65+
serviceNodeName
66+
);
6367
const { start, end } = urlParams;
6468

6569
const { data: { host, containerId } = INITIAL_DATA, status } = useFetcher(
@@ -177,25 +181,6 @@ export function ServiceNodeMetrics({ match }: ServiceNodeMetricsProps) {
177181
</EuiFlexItem>
178182
</MetadataFlexGroup>
179183
)}
180-
{agentName && (
181-
<ChartPointerEventContextProvider>
182-
<EuiFlexGrid columns={2} gutterSize="s">
183-
{data.charts.map((chart) => (
184-
<EuiFlexItem key={chart.key}>
185-
<EuiPanel>
186-
<MetricsChart
187-
start={start}
188-
end={end}
189-
chart={chart}
190-
fetchStatus={status}
191-
/>
192-
</EuiPanel>
193-
</EuiFlexItem>
194-
))}
195-
</EuiFlexGrid>
196-
<EuiSpacer size="xxl" />
197-
</ChartPointerEventContextProvider>
198-
)}
199184
<SearchBar />
200185
<EuiPage>
201186
{agentName && (

0 commit comments

Comments
 (0)