Skip to content

Commit f766bd3

Browse files
committed
Merge branch 'master' into fix/docker_config
2 parents f3388a5 + ac8cdf3 commit f766bd3

File tree

62 files changed

+3991
-1073
lines changed

Some content is hidden

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

62 files changed

+3991
-1073
lines changed

renovate.json5

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,7 @@
2727
],
2828
},
2929
separateMajorMinor: false,
30-
masterIssue: true,
31-
masterIssueApproval: false,
30+
masterIssue: false,
3231
rangeStrategy: 'bump',
3332
npm: {
3433
lockFileMaintenance: {

x-pack/plugins/ingest_manager/server/routes/limited_concurrency.test.ts

Lines changed: 186 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,12 @@
44
* you may not use this file except in compliance with the Elastic License.
55
*/
66

7-
import { coreMock } from 'src/core/server/mocks';
8-
import { registerLimitedConcurrencyRoutes } from './limited_concurrency';
7+
import { coreMock, httpServerMock, httpServiceMock } from 'src/core/server/mocks';
8+
import {
9+
createLimitedPreAuthHandler,
10+
isLimitedRoute,
11+
registerLimitedConcurrencyRoutes,
12+
} from './limited_concurrency';
913
import { IngestManagerConfigType } from '../index';
1014

1115
describe('registerLimitedConcurrencyRoutes', () => {
@@ -33,3 +37,183 @@ describe('registerLimitedConcurrencyRoutes', () => {
3337
expect(mockSetup.http.registerOnPreAuth).toHaveBeenCalledTimes(1);
3438
});
3539
});
40+
41+
// assertions for calls to .decrease are commented out because it's called on the
42+
// "req.events.aborted$ observable (which) will never emit from a mocked request in a jest unit test environment"
43+
// https://github.com/elastic/kibana/pull/72338#issuecomment-661908791
44+
describe('preAuthHandler', () => {
45+
test(`ignores routes when !isMatch`, async () => {
46+
const mockMaxCounter = {
47+
increase: jest.fn(),
48+
decrease: jest.fn(),
49+
lessThanMax: jest.fn(),
50+
};
51+
const preAuthHandler = createLimitedPreAuthHandler({
52+
isMatch: jest.fn().mockImplementation(() => false),
53+
maxCounter: mockMaxCounter,
54+
});
55+
56+
const mockRequest = httpServerMock.createKibanaRequest({
57+
path: '/no/match',
58+
});
59+
const mockResponse = httpServerMock.createResponseFactory();
60+
const mockPreAuthToolkit = httpServiceMock.createOnPreAuthToolkit();
61+
62+
await preAuthHandler(mockRequest, mockResponse, mockPreAuthToolkit);
63+
64+
expect(mockMaxCounter.increase).not.toHaveBeenCalled();
65+
expect(mockMaxCounter.decrease).not.toHaveBeenCalled();
66+
expect(mockMaxCounter.lessThanMax).not.toHaveBeenCalled();
67+
expect(mockPreAuthToolkit.next).toHaveBeenCalledTimes(1);
68+
});
69+
70+
test(`ignores routes which don't have the correct tag`, async () => {
71+
const mockMaxCounter = {
72+
increase: jest.fn(),
73+
decrease: jest.fn(),
74+
lessThanMax: jest.fn(),
75+
};
76+
const preAuthHandler = createLimitedPreAuthHandler({
77+
isMatch: isLimitedRoute,
78+
maxCounter: mockMaxCounter,
79+
});
80+
81+
const mockRequest = httpServerMock.createKibanaRequest({
82+
path: '/no/match',
83+
});
84+
const mockResponse = httpServerMock.createResponseFactory();
85+
const mockPreAuthToolkit = httpServiceMock.createOnPreAuthToolkit();
86+
87+
await preAuthHandler(mockRequest, mockResponse, mockPreAuthToolkit);
88+
89+
expect(mockMaxCounter.increase).not.toHaveBeenCalled();
90+
expect(mockMaxCounter.decrease).not.toHaveBeenCalled();
91+
expect(mockMaxCounter.lessThanMax).not.toHaveBeenCalled();
92+
expect(mockPreAuthToolkit.next).toHaveBeenCalledTimes(1);
93+
});
94+
95+
test(`processes routes which have the correct tag`, async () => {
96+
const mockMaxCounter = {
97+
increase: jest.fn(),
98+
decrease: jest.fn(),
99+
lessThanMax: jest.fn().mockImplementation(() => true),
100+
};
101+
const preAuthHandler = createLimitedPreAuthHandler({
102+
isMatch: isLimitedRoute,
103+
maxCounter: mockMaxCounter,
104+
});
105+
106+
const mockRequest = httpServerMock.createKibanaRequest({
107+
path: '/should/match',
108+
routeTags: ['ingest:limited-concurrency'],
109+
});
110+
const mockResponse = httpServerMock.createResponseFactory();
111+
const mockPreAuthToolkit = httpServiceMock.createOnPreAuthToolkit();
112+
113+
await preAuthHandler(mockRequest, mockResponse, mockPreAuthToolkit);
114+
115+
// will call lessThanMax because isMatch succeeds
116+
expect(mockMaxCounter.lessThanMax).toHaveBeenCalledTimes(1);
117+
// will not error because lessThanMax is true
118+
expect(mockResponse.customError).not.toHaveBeenCalled();
119+
expect(mockPreAuthToolkit.next).toHaveBeenCalledTimes(1);
120+
});
121+
122+
test(`updates the counter when isMatch & lessThanMax`, async () => {
123+
const mockMaxCounter = {
124+
increase: jest.fn(),
125+
decrease: jest.fn(),
126+
lessThanMax: jest.fn().mockImplementation(() => true),
127+
};
128+
const preAuthHandler = createLimitedPreAuthHandler({
129+
isMatch: jest.fn().mockImplementation(() => true),
130+
maxCounter: mockMaxCounter,
131+
});
132+
133+
const mockRequest = httpServerMock.createKibanaRequest();
134+
const mockResponse = httpServerMock.createResponseFactory();
135+
const mockPreAuthToolkit = httpServiceMock.createOnPreAuthToolkit();
136+
137+
await preAuthHandler(mockRequest, mockResponse, mockPreAuthToolkit);
138+
139+
expect(mockMaxCounter.increase).toHaveBeenCalled();
140+
// expect(mockMaxCounter.decrease).toHaveBeenCalled();
141+
expect(mockPreAuthToolkit.next).toHaveBeenCalledTimes(1);
142+
});
143+
144+
test(`lessThanMax ? next : error`, async () => {
145+
const mockMaxCounter = {
146+
increase: jest.fn(),
147+
decrease: jest.fn(),
148+
lessThanMax: jest
149+
.fn()
150+
// call 1
151+
.mockImplementationOnce(() => true)
152+
// calls 2, 3, 4
153+
.mockImplementationOnce(() => false)
154+
.mockImplementationOnce(() => false)
155+
.mockImplementationOnce(() => false)
156+
// calls 5+
157+
.mockImplementationOnce(() => true)
158+
.mockImplementation(() => true),
159+
};
160+
161+
const preAuthHandler = createLimitedPreAuthHandler({
162+
isMatch: isLimitedRoute,
163+
maxCounter: mockMaxCounter,
164+
});
165+
166+
function makeRequestExpectNext() {
167+
const request = httpServerMock.createKibanaRequest({
168+
path: '/should/match/',
169+
routeTags: ['ingest:limited-concurrency'],
170+
});
171+
const response = httpServerMock.createResponseFactory();
172+
const toolkit = httpServiceMock.createOnPreAuthToolkit();
173+
174+
preAuthHandler(request, response, toolkit);
175+
expect(toolkit.next).toHaveBeenCalledTimes(1);
176+
expect(response.customError).not.toHaveBeenCalled();
177+
}
178+
179+
function makeRequestExpectError() {
180+
const request = httpServerMock.createKibanaRequest({
181+
path: '/should/match/',
182+
routeTags: ['ingest:limited-concurrency'],
183+
});
184+
const response = httpServerMock.createResponseFactory();
185+
const toolkit = httpServiceMock.createOnPreAuthToolkit();
186+
187+
preAuthHandler(request, response, toolkit);
188+
expect(toolkit.next).not.toHaveBeenCalled();
189+
expect(response.customError).toHaveBeenCalledTimes(1);
190+
expect(response.customError).toHaveBeenCalledWith({
191+
statusCode: 429,
192+
body: 'Too Many Requests',
193+
});
194+
}
195+
196+
// request 1 succeeds
197+
makeRequestExpectNext();
198+
expect(mockMaxCounter.increase).toHaveBeenCalledTimes(1);
199+
// expect(mockMaxCounter.decrease).toHaveBeenCalledTimes(1);
200+
201+
// requests 2, 3, 4 fail
202+
makeRequestExpectError();
203+
makeRequestExpectError();
204+
makeRequestExpectError();
205+
206+
// requests 5+ succeed
207+
makeRequestExpectNext();
208+
expect(mockMaxCounter.increase).toHaveBeenCalledTimes(2);
209+
// expect(mockMaxCounter.decrease).toHaveBeenCalledTimes(2);
210+
211+
makeRequestExpectNext();
212+
expect(mockMaxCounter.increase).toHaveBeenCalledTimes(3);
213+
// expect(mockMaxCounter.decrease).toHaveBeenCalledTimes(3);
214+
215+
makeRequestExpectNext();
216+
expect(mockMaxCounter.increase).toHaveBeenCalledTimes(4);
217+
// expect(mockMaxCounter.decrease).toHaveBeenCalledTimes(4);
218+
});
219+
});

x-pack/plugins/ingest_manager/server/routes/limited_concurrency.ts

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ import {
1212
} from 'kibana/server';
1313
import { LIMITED_CONCURRENCY_ROUTE_TAG } from '../../common';
1414
import { IngestManagerConfigType } from '../index';
15-
class MaxCounter {
15+
16+
export class MaxCounter {
1617
constructor(private readonly max: number = 1) {}
1718
private counter = 0;
1819
valueOf() {
@@ -33,40 +34,56 @@ class MaxCounter {
3334
}
3435
}
3536

36-
function shouldHandleRequest(request: KibanaRequest) {
37+
export type IMaxCounter = Pick<MaxCounter, 'increase' | 'decrease' | 'lessThanMax'>;
38+
39+
export function isLimitedRoute(request: KibanaRequest) {
3740
const tags = request.route.options.tags;
38-
return tags.includes(LIMITED_CONCURRENCY_ROUTE_TAG);
41+
return !!tags.includes(LIMITED_CONCURRENCY_ROUTE_TAG);
3942
}
4043

41-
export function registerLimitedConcurrencyRoutes(core: CoreSetup, config: IngestManagerConfigType) {
42-
const max = config.fleet.maxConcurrentConnections;
43-
if (!max) return;
44-
45-
const counter = new MaxCounter(max);
46-
core.http.registerOnPreAuth(function preAuthHandler(
44+
export function createLimitedPreAuthHandler({
45+
isMatch,
46+
maxCounter,
47+
}: {
48+
isMatch: (request: KibanaRequest) => boolean;
49+
maxCounter: IMaxCounter;
50+
}) {
51+
return function preAuthHandler(
4752
request: KibanaRequest,
4853
response: LifecycleResponseFactory,
4954
toolkit: OnPreAuthToolkit
5055
) {
51-
if (!shouldHandleRequest(request)) {
56+
if (!isMatch(request)) {
5257
return toolkit.next();
5358
}
5459

55-
if (!counter.lessThanMax()) {
60+
if (!maxCounter.lessThanMax()) {
5661
return response.customError({
5762
body: 'Too Many Requests',
5863
statusCode: 429,
5964
});
6065
}
6166

62-
counter.increase();
67+
maxCounter.increase();
6368

6469
// requests.events.aborted$ has a bug (but has test which explicitly verifies) where it's fired even when the request completes
6570
// https://github.com/elastic/kibana/pull/70495#issuecomment-656288766
6671
request.events.aborted$.toPromise().then(() => {
67-
counter.decrease();
72+
maxCounter.decrease();
6873
});
6974

7075
return toolkit.next();
71-
});
76+
};
77+
}
78+
79+
export function registerLimitedConcurrencyRoutes(core: CoreSetup, config: IngestManagerConfigType) {
80+
const max = config.fleet.maxConcurrentConnections;
81+
if (!max) return;
82+
83+
core.http.registerOnPreAuth(
84+
createLimitedPreAuthHandler({
85+
isMatch: isLimitedRoute,
86+
maxCounter: new MaxCounter(max),
87+
})
88+
);
7289
}

x-pack/plugins/lists/common/constants.mock.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export const OPERATOR = 'included';
4141
export const ENTRY_VALUE = 'some host name';
4242
export const MATCH = 'match';
4343
export const MATCH_ANY = 'match_any';
44-
export const MAX_IMPORT_PAYLOAD_BYTES = 40000000;
44+
export const MAX_IMPORT_PAYLOAD_BYTES = 9000000;
4545
export const IMPORT_BUFFER_SIZE = 1000;
4646
export const LIST = 'list';
4747
export const EXISTS = 'exists';

x-pack/plugins/lists/server/config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export const ConfigSchema = schema.object({
1111
importBufferSize: schema.number({ defaultValue: 1000, min: 1 }),
1212
listIndex: schema.string({ defaultValue: '.lists' }),
1313
listItemIndex: schema.string({ defaultValue: '.items' }),
14-
maxImportPayloadBytes: schema.number({ defaultValue: 40000000, min: 1 }),
14+
maxImportPayloadBytes: schema.number({ defaultValue: 9000000, min: 1 }),
1515
});
1616

1717
export type ConfigType = TypeOf<typeof ConfigSchema>;

x-pack/plugins/maps/public/classes/layers/blended_vector_layer/blended_vector_layer.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ function getClusterSource(documentSource: IESSource, documentStyle: IVectorStyle
5555
geoField: documentSource.getGeoFieldName(),
5656
requestType: RENDER_AS.POINT,
5757
});
58+
clusterSourceDescriptor.applyGlobalQuery = documentSource.getApplyGlobalQuery();
5859
clusterSourceDescriptor.metrics = [
5960
{
6061
type: AGG_TYPE.COUNT,

x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,6 @@ export class ESGeoGridSource extends AbstractESAggSource {
161161
bounds: makeESBbox(bufferedExtent),
162162
field: this._descriptor.geoField,
163163
precision,
164-
size: DEFAULT_MAX_BUCKETS_LIMIT,
165164
},
166165
},
167166
},

x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_delete/use_delete_action.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ export const useDeleteAction = () => {
5454
);
5555
if (ip !== undefined) {
5656
setIndexPatternExists(true);
57+
} else {
58+
setIndexPatternExists(false);
5759
}
5860
} catch (e) {
5961
const { toasts } = notifications;
@@ -101,7 +103,7 @@ export const useDeleteAction = () => {
101103

102104
// Check if an user has permission to delete the index & index pattern
103105
checkUserIndexPermission();
104-
}, []);
106+
}, [isModalVisible]);
105107

106108
const closeModal = () => setModalVisible(false);
107109
const deleteAndCloseModal = () => {

0 commit comments

Comments
 (0)