Skip to content

Commit e77b45f

Browse files
[ML] Versioning file upload APIs (#158265)
Adds versioning to all of the file upload APIs. Versions are added to the server side routes and to the client side functions which call the routes. Updates API tests to add the API version to the request headers. All of the APIs are internal and have been given the version '1'. Also renames `/internal/file_data_visualizer/analyze_file` to `/internal/file_upload/analyze_file` It appears this was a mistake from when the route was moved from the data visualiser plugin midway through development on [this PR](#96408). **Internal APIs** `/internal/file_upload/analyze_file` `/internal/file_upload/has_import_permission` `/internal/file_upload/index_exists` `/internal/file_upload/time_field_range` --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
1 parent b388d70 commit e77b45f

File tree

6 files changed

+173
-124
lines changed

6 files changed

+173
-124
lines changed

x-pack/plugins/file_upload/public/api/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,9 @@ export async function analyzeFile(
5454
const { getHttp } = await lazyLoadModules();
5555
const body = JSON.stringify(file);
5656
return await getHttp().fetch<FindFileStructureResponse>({
57-
path: `/internal/file_data_visualizer/analyze_file`,
57+
path: `/internal/file_upload/analyze_file`,
5858
method: 'POST',
59+
version: '1',
5960
body,
6061
query: params,
6162
});
@@ -67,6 +68,7 @@ export async function hasImportPermission(params: HasImportPermissionParams): Pr
6768
const resp = await fileUploadModules.getHttp().fetch<HasImportPermission>({
6869
path: `/internal/file_upload/has_import_permission`,
6970
method: 'GET',
71+
version: '1',
7072
query: { ...params },
7173
});
7274
return resp.hasImportPermission;
@@ -85,6 +87,7 @@ export async function checkIndexExists(
8587
const { exists } = await fileUploadModules.getHttp().fetch<{ exists: boolean }>({
8688
path: `/internal/file_upload/index_exists`,
8789
method: 'POST',
90+
version: '1',
8891
body,
8992
query: params,
9093
});
@@ -101,6 +104,7 @@ export async function getTimeFieldRange(index: string, query: unknown, timeField
101104
return await fileUploadModules.getHttp().fetch<GetTimeFieldRangeResponse>({
102105
path: `/internal/file_upload/time_field_range`,
103106
method: 'POST',
107+
version: '1',
104108
body,
105109
});
106110
}

x-pack/plugins/file_upload/public/importer/importer.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,7 @@ export function callImportRoute({
298298
return getHttp().fetch<ImportResponse>({
299299
path: `/internal/file_upload/import`,
300300
method: 'POST',
301+
version: '1',
301302
query,
302303
body,
303304
});

x-pack/plugins/file_upload/server/routes.ts

Lines changed: 157 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -44,37 +44,44 @@ function importData(
4444
export function fileUploadRoutes(coreSetup: CoreSetup<StartDeps, unknown>, logger: Logger) {
4545
const router = coreSetup.http.createRouter();
4646

47-
router.get(
48-
{
47+
router.versioned
48+
.get({
4949
path: '/internal/file_upload/has_import_permission',
50-
validate: {
51-
query: schema.object({
52-
indexName: schema.maybe(schema.string()),
53-
checkCreateDataView: schema.boolean(),
54-
checkHasManagePipeline: schema.boolean(),
55-
}),
50+
access: 'internal',
51+
})
52+
.addVersion(
53+
{
54+
version: '1',
55+
validate: {
56+
request: {
57+
query: schema.object({
58+
indexName: schema.maybe(schema.string()),
59+
checkCreateDataView: schema.boolean(),
60+
checkHasManagePipeline: schema.boolean(),
61+
}),
62+
},
63+
},
5664
},
57-
},
58-
async (context, request, response) => {
59-
try {
60-
const [, pluginsStart] = await coreSetup.getStartServices();
61-
const { indexName, checkCreateDataView, checkHasManagePipeline } = request.query;
65+
async (context, request, response) => {
66+
try {
67+
const [, pluginsStart] = await coreSetup.getStartServices();
68+
const { indexName, checkCreateDataView, checkHasManagePipeline } = request.query;
6269

63-
const { hasImportPermission } = await checkFileUploadPrivileges({
64-
authorization: pluginsStart.security?.authz,
65-
request,
66-
indexName,
67-
checkCreateDataView,
68-
checkHasManagePipeline,
69-
});
70+
const { hasImportPermission } = await checkFileUploadPrivileges({
71+
authorization: pluginsStart.security?.authz,
72+
request,
73+
indexName,
74+
checkCreateDataView,
75+
checkHasManagePipeline,
76+
});
7077

71-
return response.ok({ body: { hasImportPermission } });
72-
} catch (e) {
73-
logger.warn(`Unable to check import permission, error: ${e.message}`);
74-
return response.ok({ body: { hasImportPermission: false } });
78+
return response.ok({ body: { hasImportPermission } });
79+
} catch (e) {
80+
logger.warn(`Unable to check import permission, error: ${e.message}`);
81+
return response.ok({ body: { hasImportPermission: false } });
82+
}
7583
}
76-
}
77-
);
84+
);
7885

7986
/**
8087
* @apiGroup FileDataVisualizer
@@ -85,31 +92,38 @@ export function fileUploadRoutes(coreSetup: CoreSetup<StartDeps, unknown>, logge
8592
*
8693
* @apiSchema (query) analyzeFileQuerySchema
8794
*/
88-
router.post(
89-
{
90-
path: '/internal/file_data_visualizer/analyze_file',
91-
validate: {
92-
body: schema.any(),
93-
query: analyzeFileQuerySchema,
94-
},
95+
router.versioned
96+
.post({
97+
path: '/internal/file_upload/analyze_file',
98+
access: 'internal',
9599
options: {
96100
body: {
97101
accepts: ['text/*', 'application/json'],
98102
maxBytes: MAX_FILE_SIZE_BYTES,
99103
},
100104
tags: ['access:fileUpload:analyzeFile'],
101105
},
102-
},
103-
async (context, request, response) => {
104-
try {
105-
const esClient = (await context.core).elasticsearch.client;
106-
const result = await analyzeFile(esClient, request.body, request.query);
107-
return response.ok({ body: result });
108-
} catch (e) {
109-
return response.customError(wrapError(e));
106+
})
107+
.addVersion(
108+
{
109+
version: '1',
110+
validate: {
111+
request: {
112+
body: schema.any(),
113+
query: analyzeFileQuerySchema,
114+
},
115+
},
116+
},
117+
async (context, request, response) => {
118+
try {
119+
const esClient = (await context.core).elasticsearch.client;
120+
const result = await analyzeFile(esClient, request.body, request.query);
121+
return response.ok({ body: result });
122+
} catch (e) {
123+
return response.customError(wrapError(e));
124+
}
110125
}
111-
}
112-
);
126+
);
113127

114128
/**
115129
* @apiGroup FileDataVisualizer
@@ -121,73 +135,87 @@ export function fileUploadRoutes(coreSetup: CoreSetup<StartDeps, unknown>, logge
121135
* @apiSchema (query) importFileQuerySchema
122136
* @apiSchema (body) importFileBodySchema
123137
*/
124-
router.post(
125-
{
138+
router.versioned
139+
.post({
126140
path: '/internal/file_upload/import',
127-
validate: {
128-
query: importFileQuerySchema,
129-
body: importFileBodySchema,
130-
},
141+
access: 'internal',
131142
options: {
132143
body: {
133144
accepts: ['application/json'],
134145
maxBytes: MAX_FILE_SIZE_BYTES,
135146
},
136147
},
137-
},
138-
async (context, request, response) => {
139-
try {
140-
const { id } = request.query;
141-
const { index, data, settings, mappings, ingestPipeline } = request.body;
142-
const esClient = (await context.core).elasticsearch.client;
148+
})
149+
.addVersion(
150+
{
151+
version: '1',
152+
validate: {
153+
request: {
154+
query: importFileQuerySchema,
155+
body: importFileBodySchema,
156+
},
157+
},
158+
},
159+
async (context, request, response) => {
160+
try {
161+
const { id } = request.query;
162+
const { index, data, settings, mappings, ingestPipeline } = request.body;
163+
const esClient = (await context.core).elasticsearch.client;
143164

144-
// `id` being `undefined` tells us that this is a new import due to create a new index.
145-
// follow-up import calls to just add additional data will include the `id` of the created
146-
// index, we'll ignore those and don't increment the counter.
147-
if (id === undefined) {
148-
await updateTelemetry();
149-
}
165+
// `id` being `undefined` tells us that this is a new import due to create a new index.
166+
// follow-up import calls to just add additional data will include the `id` of the created
167+
// index, we'll ignore those and don't increment the counter.
168+
if (id === undefined) {
169+
await updateTelemetry();
170+
}
150171

151-
const result = await importData(
152-
esClient,
153-
id,
154-
index,
155-
settings,
156-
mappings,
157-
// @ts-expect-error
158-
ingestPipeline,
159-
data
160-
);
161-
return response.ok({ body: result });
162-
} catch (e) {
163-
return response.customError(wrapError(e));
172+
const result = await importData(
173+
esClient,
174+
id,
175+
index,
176+
settings,
177+
mappings,
178+
// @ts-expect-error
179+
ingestPipeline,
180+
data
181+
);
182+
return response.ok({ body: result });
183+
} catch (e) {
184+
return response.customError(wrapError(e));
185+
}
164186
}
165-
}
166-
);
187+
);
167188

168189
/**
169190
* @apiGroup FileDataVisualizer
170191
*
171192
* @api {post} /internal/file_upload/index_exists ES indices exists wrapper checks if index exists
172193
* @apiName IndexExists
173194
*/
174-
router.post(
175-
{
195+
router.versioned
196+
.post({
176197
path: '/internal/file_upload/index_exists',
177-
validate: {
178-
body: schema.object({ index: schema.string() }),
198+
access: 'internal',
199+
})
200+
.addVersion(
201+
{
202+
version: '1',
203+
validate: {
204+
request: {
205+
body: schema.object({ index: schema.string() }),
206+
},
207+
},
179208
},
180-
},
181-
async (context, request, response) => {
182-
try {
183-
const esClient = (await context.core).elasticsearch.client;
184-
const indexExists = await esClient.asCurrentUser.indices.exists(request.body);
185-
return response.ok({ body: { exists: indexExists } });
186-
} catch (e) {
187-
return response.customError(wrapError(e));
209+
async (context, request, response) => {
210+
try {
211+
const esClient = (await context.core).elasticsearch.client;
212+
const indexExists = await esClient.asCurrentUser.indices.exists(request.body);
213+
return response.ok({ body: { exists: indexExists } });
214+
} catch (e) {
215+
return response.customError(wrapError(e));
216+
}
188217
}
189-
}
190-
);
218+
);
191219

192220
/**
193221
* @apiGroup FileDataVisualizer
@@ -201,42 +229,49 @@ export function fileUploadRoutes(coreSetup: CoreSetup<StartDeps, unknown>, logge
201229
* @apiSuccess {Object} start start of time range with epoch and string properties.
202230
* @apiSuccess {Object} end end of time range with epoch and string properties.
203231
*/
204-
router.post(
205-
{
232+
router.versioned
233+
.post({
206234
path: '/internal/file_upload/time_field_range',
207-
validate: {
208-
body: schema.object({
209-
/** Index or indexes for which to return the time range. */
210-
index: schema.oneOf([schema.string(), schema.arrayOf(schema.string())]),
211-
/** Name of the time field in the index. */
212-
timeFieldName: schema.string(),
213-
/** Query to match documents in the index(es). */
214-
query: schema.maybe(schema.any()),
215-
runtimeMappings: schema.maybe(runtimeMappingsSchema),
216-
}),
217-
},
235+
access: 'internal',
218236
options: {
219237
tags: ['access:fileUpload:analyzeFile'],
220238
},
221-
},
222-
async (context, request, response) => {
223-
try {
224-
const { index, timeFieldName, query, runtimeMappings } = request.body;
225-
const esClient = (await context.core).elasticsearch.client;
226-
const resp = await getTimeFieldRange(
227-
esClient,
228-
index,
229-
timeFieldName,
230-
query,
231-
runtimeMappings
232-
);
239+
})
240+
.addVersion(
241+
{
242+
version: '1',
243+
validate: {
244+
request: {
245+
body: schema.object({
246+
/** Index or indexes for which to return the time range. */
247+
index: schema.oneOf([schema.string(), schema.arrayOf(schema.string())]),
248+
/** Name of the time field in the index. */
249+
timeFieldName: schema.string(),
250+
/** Query to match documents in the index(es). */
251+
query: schema.maybe(schema.any()),
252+
runtimeMappings: schema.maybe(runtimeMappingsSchema),
253+
}),
254+
},
255+
},
256+
},
257+
async (context, request, response) => {
258+
try {
259+
const { index, timeFieldName, query, runtimeMappings } = request.body;
260+
const esClient = (await context.core).elasticsearch.client;
261+
const resp = await getTimeFieldRange(
262+
esClient,
263+
index,
264+
timeFieldName,
265+
query,
266+
runtimeMappings
267+
);
233268

234-
return response.ok({
235-
body: resp,
236-
});
237-
} catch (e) {
238-
return response.customError(wrapError(e));
269+
return response.ok({
270+
body: resp,
271+
});
272+
} catch (e) {
273+
return response.customError(wrapError(e));
274+
}
239275
}
240-
}
241-
);
276+
);
242277
}

0 commit comments

Comments
 (0)