mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
[Saved Objects] Allow exporting and importing hidden types (#90178)
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
3dbcc2713e
commit
c1d1b2b453
44 changed files with 1453 additions and 70 deletions
|
@ -11,8 +11,9 @@ core: {
|
|||
savedObjects: {
|
||||
client: SavedObjectsClientContract;
|
||||
typeRegistry: ISavedObjectTypeRegistry;
|
||||
exporter: ISavedObjectsExporter;
|
||||
importer: ISavedObjectsImporter;
|
||||
getClient: (options?: SavedObjectsClientProviderOptions) => SavedObjectsClientContract;
|
||||
getExporter: (client: SavedObjectsClientContract) => ISavedObjectsExporter;
|
||||
getImporter: (client: SavedObjectsClientContract) => ISavedObjectsImporter;
|
||||
};
|
||||
elasticsearch: {
|
||||
client: IScopedClusterClient;
|
||||
|
|
|
@ -18,5 +18,5 @@ export interface RequestHandlerContext
|
|||
|
||||
| Property | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| [core](./kibana-plugin-core-server.requesthandlercontext.core.md) | <code>{</code><br/><code> savedObjects: {</code><br/><code> client: SavedObjectsClientContract;</code><br/><code> typeRegistry: ISavedObjectTypeRegistry;</code><br/><code> exporter: ISavedObjectsExporter;</code><br/><code> importer: ISavedObjectsImporter;</code><br/><code> };</code><br/><code> elasticsearch: {</code><br/><code> client: IScopedClusterClient;</code><br/><code> legacy: {</code><br/><code> client: ILegacyScopedClusterClient;</code><br/><code> };</code><br/><code> };</code><br/><code> uiSettings: {</code><br/><code> client: IUiSettingsClient;</code><br/><code> };</code><br/><code> }</code> | |
|
||||
| [core](./kibana-plugin-core-server.requesthandlercontext.core.md) | <code>{</code><br/><code> savedObjects: {</code><br/><code> client: SavedObjectsClientContract;</code><br/><code> typeRegistry: ISavedObjectTypeRegistry;</code><br/><code> getClient: (options?: SavedObjectsClientProviderOptions) => SavedObjectsClientContract;</code><br/><code> getExporter: (client: SavedObjectsClientContract) => ISavedObjectsExporter;</code><br/><code> getImporter: (client: SavedObjectsClientContract) => ISavedObjectsImporter;</code><br/><code> };</code><br/><code> elasticsearch: {</code><br/><code> client: IScopedClusterClient;</code><br/><code> legacy: {</code><br/><code> client: ILegacyScopedClusterClient;</code><br/><code> };</code><br/><code> };</code><br/><code> uiSettings: {</code><br/><code> client: IUiSettingsClient;</code><br/><code> };</code><br/><code> }</code> | |
|
||||
|
||||
|
|
|
@ -13,8 +13,7 @@ import { SavedObjectsClientContract } from './saved_objects/types';
|
|||
import {
|
||||
InternalSavedObjectsServiceStart,
|
||||
ISavedObjectTypeRegistry,
|
||||
ISavedObjectsExporter,
|
||||
ISavedObjectsImporter,
|
||||
SavedObjectsClientProviderOptions,
|
||||
} from './saved_objects';
|
||||
import {
|
||||
InternalElasticsearchServiceStart,
|
||||
|
@ -58,8 +57,6 @@ class CoreSavedObjectsRouteHandlerContext {
|
|||
) {}
|
||||
#scopedSavedObjectsClient?: SavedObjectsClientContract;
|
||||
#typeRegistry?: ISavedObjectTypeRegistry;
|
||||
#exporter?: ISavedObjectsExporter;
|
||||
#importer?: ISavedObjectsImporter;
|
||||
|
||||
public get client() {
|
||||
if (this.#scopedSavedObjectsClient == null) {
|
||||
|
@ -75,19 +72,18 @@ class CoreSavedObjectsRouteHandlerContext {
|
|||
return this.#typeRegistry;
|
||||
}
|
||||
|
||||
public get exporter() {
|
||||
if (this.#exporter == null) {
|
||||
this.#exporter = this.savedObjectsStart.createExporter(this.client);
|
||||
}
|
||||
return this.#exporter;
|
||||
}
|
||||
public getClient = (options?: SavedObjectsClientProviderOptions) => {
|
||||
if (!options) return this.client;
|
||||
return this.savedObjectsStart.getScopedClient(this.request, options);
|
||||
};
|
||||
|
||||
public get importer() {
|
||||
if (this.#importer == null) {
|
||||
this.#importer = this.savedObjectsStart.createImporter(this.client);
|
||||
}
|
||||
return this.#importer;
|
||||
}
|
||||
public getExporter = (client: SavedObjectsClientContract) => {
|
||||
return this.savedObjectsStart.createExporter(client);
|
||||
};
|
||||
|
||||
public getImporter = (client: SavedObjectsClientContract) => {
|
||||
return this.savedObjectsStart.createImporter(client);
|
||||
};
|
||||
}
|
||||
|
||||
class CoreUiSettingsRouteHandlerContext {
|
||||
|
|
|
@ -49,6 +49,7 @@ import {
|
|||
SavedObjectsServiceStart,
|
||||
ISavedObjectsExporter,
|
||||
ISavedObjectsImporter,
|
||||
SavedObjectsClientProviderOptions,
|
||||
} from './saved_objects';
|
||||
import { CapabilitiesSetup, CapabilitiesStart } from './capabilities';
|
||||
import { MetricsServiceSetup, MetricsServiceStart } from './metrics';
|
||||
|
@ -415,8 +416,9 @@ export interface RequestHandlerContext {
|
|||
savedObjects: {
|
||||
client: SavedObjectsClientContract;
|
||||
typeRegistry: ISavedObjectTypeRegistry;
|
||||
exporter: ISavedObjectsExporter;
|
||||
importer: ISavedObjectsImporter;
|
||||
getClient: (options?: SavedObjectsClientProviderOptions) => SavedObjectsClientContract;
|
||||
getExporter: (client: SavedObjectsClientContract) => ISavedObjectsExporter;
|
||||
getImporter: (client: SavedObjectsClientContract) => ISavedObjectsImporter;
|
||||
};
|
||||
elasticsearch: {
|
||||
client: IScopedClusterClient;
|
||||
|
|
|
@ -196,8 +196,9 @@ function createCoreRequestHandlerContextMock() {
|
|||
savedObjects: {
|
||||
client: savedObjectsClientMock.create(),
|
||||
typeRegistry: savedObjectsTypeRegistryMock.create(),
|
||||
exporter: savedObjectsServiceMock.createExporter(),
|
||||
importer: savedObjectsServiceMock.createImporter(),
|
||||
getClient: savedObjectsClientMock.create,
|
||||
getExporter: savedObjectsServiceMock.createExporter,
|
||||
getImporter: savedObjectsServiceMock.createImporter,
|
||||
},
|
||||
elasticsearch: {
|
||||
client: elasticsearchServiceMock.createScopedClusterClient(),
|
||||
|
|
|
@ -32,11 +32,13 @@ export const registerDeleteRoute = (router: IRouter, { coreUsageData }: RouteDep
|
|||
catchAndReturnBoomErrors(async (context, req, res) => {
|
||||
const { type, id } = req.params;
|
||||
const { force } = req.query;
|
||||
const { getClient } = context.core.savedObjects;
|
||||
|
||||
const usageStatsClient = coreUsageData.getClient();
|
||||
usageStatsClient.incrementSavedObjectsDelete({ request: req }).catch(() => {});
|
||||
|
||||
const result = await context.core.savedObjects.client.delete(type, id, { force });
|
||||
const client = getClient();
|
||||
const result = await client.delete(type, id, { force });
|
||||
return res.ok({ body: result });
|
||||
})
|
||||
);
|
||||
|
|
|
@ -165,9 +165,9 @@ export const registerExportRoute = (
|
|||
},
|
||||
catchAndReturnBoomErrors(async (context, req, res) => {
|
||||
const cleaned = cleanOptions(req.body);
|
||||
const supportedTypes = context.core.savedObjects.typeRegistry
|
||||
.getImportableAndExportableTypes()
|
||||
.map((t) => t.name);
|
||||
const { typeRegistry, getExporter, getClient } = context.core.savedObjects;
|
||||
const supportedTypes = typeRegistry.getImportableAndExportableTypes().map((t) => t.name);
|
||||
|
||||
let options: EitherExportOptions;
|
||||
try {
|
||||
options = validateOptions(cleaned, {
|
||||
|
@ -181,7 +181,12 @@ export const registerExportRoute = (
|
|||
});
|
||||
}
|
||||
|
||||
const exporter = context.core.savedObjects.exporter;
|
||||
const includedHiddenTypes = supportedTypes.filter((supportedType) =>
|
||||
typeRegistry.isHidden(supportedType)
|
||||
);
|
||||
|
||||
const client = getClient({ includedHiddenTypes });
|
||||
const exporter = getExporter(client);
|
||||
|
||||
const usageStatsClient = coreUsageData.getClient();
|
||||
usageStatsClient
|
||||
|
|
|
@ -63,6 +63,7 @@ export const registerImportRoute = (
|
|||
},
|
||||
catchAndReturnBoomErrors(async (context, req, res) => {
|
||||
const { overwrite, createNewCopies } = req.query;
|
||||
const { getClient, getImporter, typeRegistry } = context.core.savedObjects;
|
||||
|
||||
const usageStatsClient = coreUsageData.getClient();
|
||||
usageStatsClient
|
||||
|
@ -84,7 +85,15 @@ export const registerImportRoute = (
|
|||
});
|
||||
}
|
||||
|
||||
const { importer } = context.core.savedObjects;
|
||||
const supportedTypes = typeRegistry.getImportableAndExportableTypes().map((t) => t.name);
|
||||
|
||||
const includedHiddenTypes = supportedTypes.filter((supportedType) =>
|
||||
typeRegistry.isHidden(supportedType)
|
||||
);
|
||||
|
||||
const client = getClient({ includedHiddenTypes });
|
||||
const importer = getImporter(client);
|
||||
|
||||
try {
|
||||
const result = await importer.import({
|
||||
readStream,
|
||||
|
|
|
@ -26,7 +26,8 @@ describe('DELETE /api/saved_objects/{type}/{id}', () => {
|
|||
|
||||
beforeEach(async () => {
|
||||
({ server, httpSetup, handlerContext } = await setupServer());
|
||||
savedObjectsClient = handlerContext.savedObjects.client;
|
||||
savedObjectsClient = handlerContext.savedObjects.getClient();
|
||||
handlerContext.savedObjects.getClient = jest.fn().mockImplementation(() => savedObjectsClient);
|
||||
|
||||
const router = httpSetup.createRouter('/api/saved_objects/');
|
||||
coreUsageStatsClient = coreUsageStatsClientMock.create();
|
||||
|
|
|
@ -40,9 +40,13 @@ describe('POST /api/saved_objects/_export', () => {
|
|||
handlerContext.savedObjects.typeRegistry.getImportableAndExportableTypes.mockReturnValue(
|
||||
allowedTypes.map(createExportableType)
|
||||
);
|
||||
exporter = handlerContext.savedObjects.exporter;
|
||||
exporter = handlerContext.savedObjects.getExporter();
|
||||
|
||||
const router = httpSetup.createRouter('/api/saved_objects/');
|
||||
handlerContext.savedObjects.getExporter = jest
|
||||
.fn()
|
||||
.mockImplementation(() => exporter as ReturnType<typeof savedObjectsExporterMock.create>);
|
||||
|
||||
coreUsageStatsClient = coreUsageStatsClientMock.create();
|
||||
coreUsageStatsClient.incrementSavedObjectsExport.mockRejectedValue(new Error('Oh no!')); // intentionally throw this error, which is swallowed, so we can assert that the operation does not fail
|
||||
const coreUsageData = coreUsageDataServiceMock.createSetupContract(coreUsageStatsClient);
|
||||
|
@ -77,6 +81,7 @@ describe('POST /api/saved_objects/_export', () => {
|
|||
],
|
||||
},
|
||||
];
|
||||
|
||||
exporter.exportByTypes.mockResolvedValueOnce(createListStream(sortedObjects));
|
||||
|
||||
const result = await supertest(httpSetup.server.listener)
|
||||
|
|
|
@ -68,9 +68,9 @@ describe(`POST ${URL}`, () => {
|
|||
typeRegistry: handlerContext.savedObjects.typeRegistry,
|
||||
importSizeLimit: 10000,
|
||||
});
|
||||
handlerContext.savedObjects.importer.import.mockImplementation((options) =>
|
||||
importer.import(options)
|
||||
);
|
||||
handlerContext.savedObjects.getImporter = jest
|
||||
.fn()
|
||||
.mockImplementation(() => importer as jest.Mocked<SavedObjectsImporter>);
|
||||
|
||||
const router = httpSetup.createRouter('/internal/saved_objects/');
|
||||
coreUsageStatsClient = coreUsageStatsClientMock.create();
|
||||
|
|
|
@ -66,7 +66,7 @@ describe(`POST ${URL}`, () => {
|
|||
} as any)
|
||||
);
|
||||
|
||||
savedObjectsClient = handlerContext.savedObjects.client;
|
||||
savedObjectsClient = handlerContext.savedObjects.getClient();
|
||||
savedObjectsClient.checkConflicts.mockResolvedValue({ errors: [] });
|
||||
|
||||
const importer = new SavedObjectsImporter({
|
||||
|
@ -74,9 +74,10 @@ describe(`POST ${URL}`, () => {
|
|||
typeRegistry: handlerContext.savedObjects.typeRegistry,
|
||||
importSizeLimit: 10000,
|
||||
});
|
||||
handlerContext.savedObjects.importer.resolveImportErrors.mockImplementation((options) =>
|
||||
importer.resolveImportErrors(options)
|
||||
);
|
||||
|
||||
handlerContext.savedObjects.getImporter = jest
|
||||
.fn()
|
||||
.mockImplementation(() => importer as jest.Mocked<SavedObjectsImporter>);
|
||||
|
||||
const router = httpSetup.createRouter('/api/saved_objects/');
|
||||
coreUsageStatsClient = coreUsageStatsClientMock.create();
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
import { extname } from 'path';
|
||||
import { Readable } from 'stream';
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import { chain } from 'lodash';
|
||||
import { IRouter } from '../../http';
|
||||
import { CoreUsageDataSetup } from '../../core_usage_data';
|
||||
import { SavedObjectConfig } from '../saved_objects_config';
|
||||
|
@ -91,7 +92,18 @@ export const registerResolveImportErrorsRoute = (
|
|||
});
|
||||
}
|
||||
|
||||
const { importer } = context.core.savedObjects;
|
||||
const { getClient, getImporter, typeRegistry } = context.core.savedObjects;
|
||||
|
||||
const includedHiddenTypes = chain(req.body.retries)
|
||||
.map('type')
|
||||
.uniq()
|
||||
.filter(
|
||||
(type) => typeRegistry.isHidden(type) && typeRegistry.isImportableAndExportable(type)
|
||||
)
|
||||
.value();
|
||||
|
||||
const client = getClient({ includedHiddenTypes });
|
||||
const importer = getImporter(client);
|
||||
|
||||
try {
|
||||
const result = await importer.resolveImportErrors({
|
||||
|
|
|
@ -1924,8 +1924,9 @@ export interface RequestHandlerContext {
|
|||
savedObjects: {
|
||||
client: SavedObjectsClientContract;
|
||||
typeRegistry: ISavedObjectTypeRegistry;
|
||||
exporter: ISavedObjectsExporter;
|
||||
importer: ISavedObjectsImporter;
|
||||
getClient: (options?: SavedObjectsClientProviderOptions) => SavedObjectsClientContract;
|
||||
getExporter: (client: SavedObjectsClientContract) => ISavedObjectsExporter;
|
||||
getImporter: (client: SavedObjectsClientContract) => ISavedObjectsImporter;
|
||||
};
|
||||
elasticsearch: {
|
||||
client: IScopedClusterClient;
|
||||
|
|
|
@ -143,7 +143,15 @@ export function createInstallRoute(
|
|||
|
||||
let createResults;
|
||||
try {
|
||||
createResults = await context.core.savedObjects.client.bulkCreate(
|
||||
const { getClient, typeRegistry } = context.core.savedObjects;
|
||||
|
||||
const includedHiddenTypes = sampleDataset.savedObjects
|
||||
.map((object) => object.type)
|
||||
.filter((supportedType) => typeRegistry.isHidden(supportedType));
|
||||
|
||||
const client = getClient({ includedHiddenTypes });
|
||||
|
||||
createResults = await client.bulkCreate(
|
||||
sampleDataset.savedObjects.map(({ version, ...savedObject }) => savedObject),
|
||||
{ overwrite: true }
|
||||
);
|
||||
|
@ -156,8 +164,8 @@ export function createInstallRoute(
|
|||
return Boolean(savedObjectCreateResult.error);
|
||||
});
|
||||
if (errors.length > 0) {
|
||||
const errMsg = `sample_data install errors while loading saved objects. Errors: ${errors.join(
|
||||
','
|
||||
const errMsg = `sample_data install errors while loading saved objects. Errors: ${JSON.stringify(
|
||||
errors
|
||||
)}`;
|
||||
logger.warn(errMsg);
|
||||
return res.customError({ body: errMsg, statusCode: 403 });
|
||||
|
|
|
@ -33,7 +33,7 @@ export function createUninstallRoute(
|
|||
client: { callAsCurrentUser },
|
||||
},
|
||||
},
|
||||
savedObjects: { client: savedObjectsClient },
|
||||
savedObjects: { getClient: getSavedObjectsClient, typeRegistry },
|
||||
},
|
||||
},
|
||||
request,
|
||||
|
@ -61,6 +61,12 @@ export function createUninstallRoute(
|
|||
}
|
||||
}
|
||||
|
||||
const includedHiddenTypes = sampleDataset.savedObjects
|
||||
.map((object) => object.type)
|
||||
.filter((supportedType) => typeRegistry.isHidden(supportedType));
|
||||
|
||||
const savedObjectsClient = getSavedObjectsClient({ includedHiddenTypes });
|
||||
|
||||
const deletePromises = sampleDataset.savedObjects.map(({ type, id }) =>
|
||||
savedObjectsClient.delete(type, id)
|
||||
);
|
||||
|
|
|
@ -123,7 +123,10 @@ const CountIndicators: FC<{ importItems: ImportItem[] }> = ({ importItems }) =>
|
|||
{errorCount && (
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiTitle size="xs">
|
||||
<h4 className="savedObjectsManagementImportSummary__errorCount">
|
||||
<h4
|
||||
data-test-subj="importSavedObjectsErrorsCount"
|
||||
className="savedObjectsManagementImportSummary__errorCount"
|
||||
>
|
||||
<FormattedMessage
|
||||
id="savedObjectsManagement.importSummary.errorCountHeader"
|
||||
defaultMessage="{errorCount} error"
|
||||
|
|
|
@ -45,17 +45,24 @@ export const registerFindRoute = (
|
|||
},
|
||||
},
|
||||
router.handleLegacyErrors(async (context, req, res) => {
|
||||
const { query } = req;
|
||||
const managementService = await managementServicePromise;
|
||||
const { client } = context.core.savedObjects;
|
||||
const searchTypes = Array.isArray(req.query.type) ? req.query.type : [req.query.type];
|
||||
const includedFields = Array.isArray(req.query.fields)
|
||||
? req.query.fields
|
||||
: [req.query.fields];
|
||||
const { getClient, typeRegistry } = context.core.savedObjects;
|
||||
|
||||
const searchTypes = Array.isArray(query.type) ? query.type : [query.type];
|
||||
const includedFields = Array.isArray(query.fields) ? query.fields : [query.fields];
|
||||
|
||||
const importAndExportableTypes = searchTypes.filter((type) =>
|
||||
managementService.isImportAndExportable(type)
|
||||
typeRegistry.isImportableAndExportable(type)
|
||||
);
|
||||
|
||||
const includedHiddenTypes = importAndExportableTypes.filter((type) =>
|
||||
typeRegistry.isHidden(type)
|
||||
);
|
||||
|
||||
const client = getClient({ includedHiddenTypes });
|
||||
const searchFields = new Set<string>();
|
||||
|
||||
importAndExportableTypes.forEach((type) => {
|
||||
const searchField = managementService.getDefaultSearchField(type);
|
||||
if (searchField) {
|
||||
|
@ -64,7 +71,7 @@ export const registerFindRoute = (
|
|||
});
|
||||
|
||||
const findResponse = await client.find<any>({
|
||||
...req.query,
|
||||
...query,
|
||||
fields: undefined,
|
||||
searchFields: [...searchFields],
|
||||
});
|
||||
|
|
|
@ -26,10 +26,14 @@ export const registerGetRoute = (
|
|||
},
|
||||
},
|
||||
router.handleLegacyErrors(async (context, req, res) => {
|
||||
const managementService = await managementServicePromise;
|
||||
const { client } = context.core.savedObjects;
|
||||
|
||||
const { type, id } = req.params;
|
||||
const managementService = await managementServicePromise;
|
||||
const { getClient, typeRegistry } = context.core.savedObjects;
|
||||
const includedHiddenTypes = [type].filter(
|
||||
(entry) => typeRegistry.isHidden(entry) && typeRegistry.isImportableAndExportable(entry)
|
||||
);
|
||||
|
||||
const client = getClient({ includedHiddenTypes });
|
||||
const findResponse = await client.get<any>(type, id);
|
||||
|
||||
const enhancedSavedObject = injectMetaAttributes(findResponse, managementService);
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import { IRouter } from 'src/core/server';
|
||||
import { chain } from 'lodash';
|
||||
import { findRelationships } from '../lib';
|
||||
import { ISavedObjectsManagement } from '../services';
|
||||
|
||||
|
@ -31,12 +32,21 @@ export const registerRelationshipsRoute = (
|
|||
},
|
||||
router.handleLegacyErrors(async (context, req, res) => {
|
||||
const managementService = await managementServicePromise;
|
||||
const { client } = context.core.savedObjects;
|
||||
const { getClient, typeRegistry } = context.core.savedObjects;
|
||||
const { type, id } = req.params;
|
||||
const { size } = req.query;
|
||||
const savedObjectTypes = Array.isArray(req.query.savedObjectTypes)
|
||||
? req.query.savedObjectTypes
|
||||
: [req.query.savedObjectTypes];
|
||||
const { size, savedObjectTypes: maybeArraySavedObjectTypes } = req.query;
|
||||
const savedObjectTypes = Array.isArray(maybeArraySavedObjectTypes)
|
||||
? maybeArraySavedObjectTypes
|
||||
: [maybeArraySavedObjectTypes];
|
||||
|
||||
const includedHiddenTypes = chain(maybeArraySavedObjectTypes)
|
||||
.uniq()
|
||||
.filter(
|
||||
(entry) => typeRegistry.isHidden(entry) && typeRegistry.isImportableAndExportable(entry)
|
||||
)
|
||||
.value();
|
||||
|
||||
const client = getClient({ includedHiddenTypes });
|
||||
|
||||
const findRelationsResponse = await findRelationships({
|
||||
type,
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import { IRouter, SavedObjectsFindOptions } from 'src/core/server';
|
||||
import { chain } from 'lodash';
|
||||
import { findAll } from '../lib';
|
||||
|
||||
export const registerScrollForCountRoute = (router: IRouter) => {
|
||||
|
@ -30,18 +31,27 @@ export const registerScrollForCountRoute = (router: IRouter) => {
|
|||
},
|
||||
},
|
||||
router.handleLegacyErrors(async (context, req, res) => {
|
||||
const { client } = context.core.savedObjects;
|
||||
const { getClient, typeRegistry } = context.core.savedObjects;
|
||||
const { typesToInclude, searchString, references } = req.body;
|
||||
|
||||
const includedHiddenTypes = chain(typesToInclude)
|
||||
.uniq()
|
||||
.filter(
|
||||
(type) => typeRegistry.isHidden(type) && typeRegistry.isImportableAndExportable(type)
|
||||
)
|
||||
.value();
|
||||
|
||||
const client = getClient({ includedHiddenTypes });
|
||||
const findOptions: SavedObjectsFindOptions = {
|
||||
type: req.body.typesToInclude,
|
||||
type: typesToInclude,
|
||||
perPage: 1000,
|
||||
};
|
||||
if (req.body.searchString) {
|
||||
findOptions.search = `${req.body.searchString}*`;
|
||||
if (searchString) {
|
||||
findOptions.search = `${searchString}*`;
|
||||
findOptions.searchFields = ['title'];
|
||||
}
|
||||
if (req.body.references) {
|
||||
findOptions.hasReference = req.body.references;
|
||||
if (references) {
|
||||
findOptions.hasReference = references;
|
||||
findOptions.hasReferenceOperator = 'OR';
|
||||
}
|
||||
|
||||
|
@ -54,7 +64,7 @@ export const registerScrollForCountRoute = (router: IRouter) => {
|
|||
return accum;
|
||||
}, {} as Record<string, number>);
|
||||
|
||||
for (const type of req.body.typesToInclude) {
|
||||
for (const type of typesToInclude) {
|
||||
if (!counts[type]) {
|
||||
counts[type] = 0;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import { IRouter } from 'src/core/server';
|
||||
import { chain } from 'lodash';
|
||||
import { findAll } from '../lib';
|
||||
|
||||
export const registerScrollForExportRoute = (router: IRouter) => {
|
||||
|
@ -21,10 +22,20 @@ export const registerScrollForExportRoute = (router: IRouter) => {
|
|||
},
|
||||
},
|
||||
router.handleLegacyErrors(async (context, req, res) => {
|
||||
const { client } = context.core.savedObjects;
|
||||
const { typesToInclude } = req.body;
|
||||
const { getClient, typeRegistry } = context.core.savedObjects;
|
||||
const includedHiddenTypes = chain(typesToInclude)
|
||||
.uniq()
|
||||
.filter(
|
||||
(type) => typeRegistry.isHidden(type) && typeRegistry.isImportableAndExportable(type)
|
||||
)
|
||||
.value();
|
||||
|
||||
const client = getClient({ includedHiddenTypes });
|
||||
|
||||
const objects = await findAll(client, {
|
||||
perPage: 1000,
|
||||
type: req.body.typesToInclude,
|
||||
type: typesToInclude,
|
||||
});
|
||||
|
||||
return res.ok({
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"type": "doc",
|
||||
"value": {
|
||||
"index": ".kibana",
|
||||
"id": "test-hidden-importable-exportable:ff3733a0-9fty-11e7-ahb3-3dcb94193fab",
|
||||
"source": {
|
||||
"type": "test-hidden-importable-exportable",
|
||||
"updated_at": "2021-02-11T18:51:23.794Z",
|
||||
"test-hidden-importable-exportable": {
|
||||
"title": "Hidden Saved object type that is importable/exportable."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"type": "doc",
|
||||
"value": {
|
||||
"index": ".kibana",
|
||||
"id": "test-hidden-non-importable-exportable:op3767a1-9rcg-53u7-jkb3-3dnb74193awc",
|
||||
"source": {
|
||||
"type": "test-hidden-non-importable-exportable",
|
||||
"updated_at": "2021-02-11T18:51:23.794Z",
|
||||
"test-hidden-non-importable-exportable": {
|
||||
"title": "Hidden Saved object type that is not importable/exportable."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,513 @@
|
|||
{
|
||||
"type": "index",
|
||||
"value": {
|
||||
"index": ".kibana",
|
||||
"settings": {
|
||||
"index": {
|
||||
"number_of_shards": "1",
|
||||
"auto_expand_replicas": "0-1",
|
||||
"number_of_replicas": "0"
|
||||
}
|
||||
},
|
||||
"mappings": {
|
||||
"dynamic": "strict",
|
||||
"properties": {
|
||||
"test-export-transform": {
|
||||
"properties": {
|
||||
"title": { "type": "text" },
|
||||
"enabled": { "type": "boolean" }
|
||||
}
|
||||
},
|
||||
"test-export-add": {
|
||||
"properties": {
|
||||
"title": { "type": "text" }
|
||||
}
|
||||
},
|
||||
"test-export-add-dep": {
|
||||
"properties": {
|
||||
"title": { "type": "text" }
|
||||
}
|
||||
},
|
||||
"test-export-transform-error": {
|
||||
"properties": {
|
||||
"title": { "type": "text" }
|
||||
}
|
||||
},
|
||||
"test-export-invalid-transform": {
|
||||
"properties": {
|
||||
"title": { "type": "text" }
|
||||
}
|
||||
},
|
||||
"apm-telemetry": {
|
||||
"properties": {
|
||||
"has_any_services": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"services_per_agent": {
|
||||
"properties": {
|
||||
"go": {
|
||||
"type": "long",
|
||||
"null_value": 0
|
||||
},
|
||||
"java": {
|
||||
"type": "long",
|
||||
"null_value": 0
|
||||
},
|
||||
"js-base": {
|
||||
"type": "long",
|
||||
"null_value": 0
|
||||
},
|
||||
"nodejs": {
|
||||
"type": "long",
|
||||
"null_value": 0
|
||||
},
|
||||
"python": {
|
||||
"type": "long",
|
||||
"null_value": 0
|
||||
},
|
||||
"ruby": {
|
||||
"type": "long",
|
||||
"null_value": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"canvas-workpad": {
|
||||
"dynamic": "false",
|
||||
"properties": {
|
||||
"@created": {
|
||||
"type": "date"
|
||||
},
|
||||
"@timestamp": {
|
||||
"type": "date"
|
||||
},
|
||||
"id": {
|
||||
"type": "text",
|
||||
"index": false
|
||||
},
|
||||
"name": {
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"dynamic": "true",
|
||||
"properties": {
|
||||
"accessibility:disableAnimations": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"buildNum": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"dateFormat:tz": {
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"defaultIndex": {
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"telemetry:optIn": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dashboard": {
|
||||
"properties": {
|
||||
"description": {
|
||||
"type": "text"
|
||||
},
|
||||
"hits": {
|
||||
"type": "integer"
|
||||
},
|
||||
"kibanaSavedObjectMeta": {
|
||||
"properties": {
|
||||
"searchSourceJSON": {
|
||||
"type": "text"
|
||||
}
|
||||
}
|
||||
},
|
||||
"optionsJSON": {
|
||||
"type": "text"
|
||||
},
|
||||
"panelsJSON": {
|
||||
"type": "text"
|
||||
},
|
||||
"refreshInterval": {
|
||||
"properties": {
|
||||
"display": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"pause": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"section": {
|
||||
"type": "integer"
|
||||
},
|
||||
"value": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"timeFrom": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"timeRestore": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"timeTo": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"title": {
|
||||
"type": "text"
|
||||
},
|
||||
"uiStateJSON": {
|
||||
"type": "text"
|
||||
},
|
||||
"version": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"map": {
|
||||
"properties": {
|
||||
"bounds": {
|
||||
"type": "geo_shape",
|
||||
"tree": "quadtree"
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
},
|
||||
"layerListJSON": {
|
||||
"type": "text"
|
||||
},
|
||||
"mapStateJSON": {
|
||||
"type": "text"
|
||||
},
|
||||
"title": {
|
||||
"type": "text"
|
||||
},
|
||||
"uiStateJSON": {
|
||||
"type": "text"
|
||||
},
|
||||
"version": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"graph-workspace": {
|
||||
"properties": {
|
||||
"description": {
|
||||
"type": "text"
|
||||
},
|
||||
"kibanaSavedObjectMeta": {
|
||||
"properties": {
|
||||
"searchSourceJSON": {
|
||||
"type": "text"
|
||||
}
|
||||
}
|
||||
},
|
||||
"numLinks": {
|
||||
"type": "integer"
|
||||
},
|
||||
"numVertices": {
|
||||
"type": "integer"
|
||||
},
|
||||
"title": {
|
||||
"type": "text"
|
||||
},
|
||||
"version": {
|
||||
"type": "integer"
|
||||
},
|
||||
"wsState": {
|
||||
"type": "text"
|
||||
}
|
||||
}
|
||||
},
|
||||
"index-pattern": {
|
||||
"properties": {
|
||||
"fieldFormatMap": {
|
||||
"type": "text"
|
||||
},
|
||||
"fields": {
|
||||
"type": "text"
|
||||
},
|
||||
"intervalName": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"notExpandable": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"sourceFilters": {
|
||||
"type": "text"
|
||||
},
|
||||
"timeFieldName": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"title": {
|
||||
"type": "text"
|
||||
},
|
||||
"type": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"typeMeta": {
|
||||
"type": "keyword"
|
||||
}
|
||||
}
|
||||
},
|
||||
"kql-telemetry": {
|
||||
"properties": {
|
||||
"optInCount": {
|
||||
"type": "long"
|
||||
},
|
||||
"optOutCount": {
|
||||
"type": "long"
|
||||
}
|
||||
}
|
||||
},
|
||||
"migrationVersion": {
|
||||
"dynamic": "true",
|
||||
"properties": {
|
||||
"index-pattern": {
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"space": {
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"namespace": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"search": {
|
||||
"properties": {
|
||||
"columns": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
},
|
||||
"hits": {
|
||||
"type": "integer"
|
||||
},
|
||||
"kibanaSavedObjectMeta": {
|
||||
"properties": {
|
||||
"searchSourceJSON": {
|
||||
"type": "text"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sort": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"title": {
|
||||
"type": "text"
|
||||
},
|
||||
"version": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"server": {
|
||||
"properties": {
|
||||
"uuid": {
|
||||
"type": "keyword"
|
||||
}
|
||||
}
|
||||
},
|
||||
"space": {
|
||||
"properties": {
|
||||
"_reserved": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"color": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
},
|
||||
"disabledFeatures": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"initials": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"name": {
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"ignore_above": 2048
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"spaceId": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"telemetry": {
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"timelion-sheet": {
|
||||
"properties": {
|
||||
"description": {
|
||||
"type": "text"
|
||||
},
|
||||
"hits": {
|
||||
"type": "integer"
|
||||
},
|
||||
"kibanaSavedObjectMeta": {
|
||||
"properties": {
|
||||
"searchSourceJSON": {
|
||||
"type": "text"
|
||||
}
|
||||
}
|
||||
},
|
||||
"timelion_chart_height": {
|
||||
"type": "integer"
|
||||
},
|
||||
"timelion_columns": {
|
||||
"type": "integer"
|
||||
},
|
||||
"timelion_interval": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"timelion_other_interval": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"timelion_rows": {
|
||||
"type": "integer"
|
||||
},
|
||||
"timelion_sheet": {
|
||||
"type": "text"
|
||||
},
|
||||
"title": {
|
||||
"type": "text"
|
||||
},
|
||||
"version": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"updated_at": {
|
||||
"type": "date"
|
||||
},
|
||||
"url": {
|
||||
"properties": {
|
||||
"accessCount": {
|
||||
"type": "long"
|
||||
},
|
||||
"accessDate": {
|
||||
"type": "date"
|
||||
},
|
||||
"createDate": {
|
||||
"type": "date"
|
||||
},
|
||||
"url": {
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"ignore_above": 2048
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"visualization": {
|
||||
"properties": {
|
||||
"description": {
|
||||
"type": "text"
|
||||
},
|
||||
"kibanaSavedObjectMeta": {
|
||||
"properties": {
|
||||
"searchSourceJSON": {
|
||||
"type": "text"
|
||||
}
|
||||
}
|
||||
},
|
||||
"savedSearchId": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"title": {
|
||||
"type": "text"
|
||||
},
|
||||
"uiStateJSON": {
|
||||
"type": "text"
|
||||
},
|
||||
"version": {
|
||||
"type": "integer"
|
||||
},
|
||||
"visState": {
|
||||
"type": "text"
|
||||
}
|
||||
}
|
||||
},
|
||||
"references": {
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"name": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"type": {
|
||||
"type": "keyword"
|
||||
}
|
||||
},
|
||||
"type": "nested"
|
||||
},
|
||||
"test-hidden-non-importable-exportable": {
|
||||
"properties": {
|
||||
"title": {
|
||||
"type": "text"
|
||||
}
|
||||
}
|
||||
},
|
||||
"test-hidden-importable-exportable": {
|
||||
"properties": {
|
||||
"title": {
|
||||
"type": "text"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -315,6 +315,18 @@ export function SavedObjectsPageProvider({ getService, getPageObjects }: FtrProv
|
|||
})
|
||||
);
|
||||
}
|
||||
|
||||
async getImportErrorsCount() {
|
||||
log.debug(`Toggling overwriteAll`);
|
||||
const errorCountNode = await testSubjects.find('importSavedObjectsErrorsCount');
|
||||
const errorCountText = await errorCountNode.getVisibleText();
|
||||
const match = errorCountText.match(/(\d)+/);
|
||||
if (!match) {
|
||||
throw Error(`unable to parse error count from text ${errorCountText}`);
|
||||
}
|
||||
|
||||
return +match[1];
|
||||
}
|
||||
}
|
||||
|
||||
return new SavedObjectsPage();
|
||||
|
|
|
@ -30,6 +30,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) {
|
|||
require.resolve('./test_suites/application_links'),
|
||||
require.resolve('./test_suites/data_plugin'),
|
||||
require.resolve('./test_suites/saved_objects_management'),
|
||||
require.resolve('./test_suites/saved_objects_hidden_type'),
|
||||
],
|
||||
services: {
|
||||
...functionalConfig.get('services'),
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"id": "savedObjectsHiddenType",
|
||||
"version": "0.0.1",
|
||||
"kibanaVersion": "kibana",
|
||||
"configPath": ["saved_objects_hidden_type"],
|
||||
"server": true,
|
||||
"ui": false
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"name": "saved_objects_hidden_type",
|
||||
"version": "1.0.0",
|
||||
"main": "target/test/plugin_functional/plugins/saved_objects_hidden_type",
|
||||
"kibana": {
|
||||
"version": "kibana",
|
||||
"templateVersion": "1.0.0"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"scripts": {
|
||||
"kbn": "node ../../../../scripts/kbn.js",
|
||||
"build": "rm -rf './target' && ../../../../node_modules/.bin/tsc"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { SavedObjectsHiddenTypePlugin } from './plugin';
|
||||
|
||||
export const plugin = () => new SavedObjectsHiddenTypePlugin();
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { Plugin, CoreSetup } from 'kibana/server';
|
||||
|
||||
export class SavedObjectsHiddenTypePlugin implements Plugin {
|
||||
public setup({ savedObjects }: CoreSetup, deps: {}) {
|
||||
// example of a SO type that is hidden and importableAndExportable
|
||||
savedObjects.registerType({
|
||||
name: 'test-hidden-importable-exportable',
|
||||
hidden: true,
|
||||
namespaceType: 'single',
|
||||
mappings: {
|
||||
properties: {
|
||||
title: { type: 'text' },
|
||||
},
|
||||
},
|
||||
management: {
|
||||
importableAndExportable: true,
|
||||
},
|
||||
});
|
||||
|
||||
// example of a SO type that is hidden and not importableAndExportable
|
||||
savedObjects.registerType({
|
||||
name: 'test-hidden-non-importable-exportable',
|
||||
hidden: true,
|
||||
namespaceType: 'single',
|
||||
mappings: {
|
||||
properties: {
|
||||
title: { type: 'text' },
|
||||
},
|
||||
},
|
||||
management: {
|
||||
importableAndExportable: false,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
public start() {}
|
||||
public stop() {}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"extends": "../../../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./target",
|
||||
"skipLibCheck": true
|
||||
},
|
||||
"include": [
|
||||
"index.ts",
|
||||
"server/**/*.ts",
|
||||
"../../../../typings/**/*",
|
||||
],
|
||||
"exclude": [],
|
||||
"references": [
|
||||
{ "path": "../../../../src/core/tsconfig.json" }
|
||||
]
|
||||
}
|
|
@ -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
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import expect from '@kbn/expect';
|
||||
import { PluginFunctionalProviderContext } from '../../services';
|
||||
|
||||
export default function ({ getService }: PluginFunctionalProviderContext) {
|
||||
const supertest = getService('supertest');
|
||||
const esArchiver = getService('esArchiver');
|
||||
|
||||
describe('delete', () => {
|
||||
before(() =>
|
||||
esArchiver.load(
|
||||
'../functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects'
|
||||
)
|
||||
);
|
||||
after(() =>
|
||||
esArchiver.unload(
|
||||
'../functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects'
|
||||
)
|
||||
);
|
||||
|
||||
it('should return generic 404 when trying to delete a doc with importableAndExportable types', async () =>
|
||||
await supertest
|
||||
.delete(
|
||||
`/api/saved_objects/test-hidden-importable-exportable/ff3733a0-9fty-11e7-ahb3-3dcb94193fab`
|
||||
)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.expect(404)
|
||||
.then((resp) => {
|
||||
expect(resp.body).to.eql({
|
||||
statusCode: 404,
|
||||
error: 'Not Found',
|
||||
message:
|
||||
'Saved object [test-hidden-importable-exportable/ff3733a0-9fty-11e7-ahb3-3dcb94193fab] not found',
|
||||
});
|
||||
}));
|
||||
|
||||
it('returns empty response for non importableAndExportable types', async () =>
|
||||
await supertest
|
||||
.delete(
|
||||
`/api/saved_objects/test-hidden-non-importable-exportable/op3767a1-9rcg-53u7-jkb3-3dnb74193awc`
|
||||
)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.expect(404)
|
||||
.then((resp) => {
|
||||
expect(resp.body).to.eql({
|
||||
statusCode: 404,
|
||||
error: 'Not Found',
|
||||
message:
|
||||
'Saved object [test-hidden-non-importable-exportable/op3767a1-9rcg-53u7-jkb3-3dnb74193awc] not found',
|
||||
});
|
||||
}));
|
||||
});
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import expect from '@kbn/expect';
|
||||
import { PluginFunctionalProviderContext } from '../../services';
|
||||
|
||||
function ndjsonToObject(input: string): string[] {
|
||||
return input.split('\n').map((str) => JSON.parse(str));
|
||||
}
|
||||
|
||||
export default function ({ getService }: PluginFunctionalProviderContext) {
|
||||
const supertest = getService('supertest');
|
||||
const esArchiver = getService('esArchiver');
|
||||
|
||||
describe('export', () => {
|
||||
before(() =>
|
||||
esArchiver.load(
|
||||
'../functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects'
|
||||
)
|
||||
);
|
||||
after(() =>
|
||||
esArchiver.unload(
|
||||
'../functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects'
|
||||
)
|
||||
);
|
||||
|
||||
it('exports objects with importableAndExportable types', async () =>
|
||||
await supertest
|
||||
.post('/api/saved_objects/_export')
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send({
|
||||
type: ['test-hidden-importable-exportable'],
|
||||
})
|
||||
.expect(200)
|
||||
.then((resp) => {
|
||||
const objects = ndjsonToObject(resp.text);
|
||||
expect(objects).to.have.length(2);
|
||||
expect(objects[0]).to.have.property('id', 'ff3733a0-9fty-11e7-ahb3-3dcb94193fab');
|
||||
expect(objects[0]).to.have.property('type', 'test-hidden-importable-exportable');
|
||||
}));
|
||||
|
||||
it('excludes objects with non importableAndExportable types', async () =>
|
||||
await supertest
|
||||
.post('/api/saved_objects/_export')
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send({
|
||||
type: ['test-hidden-non-importable-exportable'],
|
||||
})
|
||||
.then((resp) => {
|
||||
expect(resp.body).to.eql({
|
||||
statusCode: 400,
|
||||
error: 'Bad Request',
|
||||
message:
|
||||
'Trying to export non-exportable type(s): test-hidden-non-importable-exportable',
|
||||
});
|
||||
}));
|
||||
});
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import expect from '@kbn/expect';
|
||||
import { PluginFunctionalProviderContext } from '../../services';
|
||||
|
||||
export default function ({ getService }: PluginFunctionalProviderContext) {
|
||||
const supertest = getService('supertest');
|
||||
const esArchiver = getService('esArchiver');
|
||||
|
||||
describe('find', () => {
|
||||
before(() =>
|
||||
esArchiver.load(
|
||||
'../functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects'
|
||||
)
|
||||
);
|
||||
after(() =>
|
||||
esArchiver.unload(
|
||||
'../functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects'
|
||||
)
|
||||
);
|
||||
|
||||
it('returns empty response for importableAndExportable types', async () =>
|
||||
await supertest
|
||||
.get('/api/saved_objects/_find?type=test-hidden-importable-exportable&fields=title')
|
||||
.set('kbn-xsrf', 'true')
|
||||
.expect(200)
|
||||
.then((resp) => {
|
||||
expect(resp.body).to.eql({
|
||||
page: 1,
|
||||
per_page: 20,
|
||||
total: 0,
|
||||
saved_objects: [],
|
||||
});
|
||||
}));
|
||||
|
||||
it('returns empty response for non importableAndExportable types', async () =>
|
||||
await supertest
|
||||
.get('/api/saved_objects/_find?type=test-hidden-non-importable-exportable&fields=title')
|
||||
.set('kbn-xsrf', 'true')
|
||||
.expect(200)
|
||||
.then((resp) => {
|
||||
expect(resp.body).to.eql({
|
||||
page: 1,
|
||||
per_page: 20,
|
||||
total: 0,
|
||||
saved_objects: [],
|
||||
});
|
||||
}));
|
||||
});
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import expect from '@kbn/expect';
|
||||
import { PluginFunctionalProviderContext } from '../../services';
|
||||
|
||||
export default function ({ getService }: PluginFunctionalProviderContext) {
|
||||
const supertest = getService('supertest');
|
||||
const esArchiver = getService('esArchiver');
|
||||
|
||||
describe('import', () => {
|
||||
before(() =>
|
||||
esArchiver.load(
|
||||
'../functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects'
|
||||
)
|
||||
);
|
||||
after(() =>
|
||||
esArchiver.unload(
|
||||
'../functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects'
|
||||
)
|
||||
);
|
||||
|
||||
it('imports objects with importableAndExportable type', async () => {
|
||||
const fileBuffer = Buffer.from(
|
||||
'{"id":"some-id-1","type":"test-hidden-importable-exportable","attributes":{"title":"my title"},"references":[]}',
|
||||
'utf8'
|
||||
);
|
||||
await supertest
|
||||
.post('/api/saved_objects/_import')
|
||||
.set('kbn-xsrf', 'true')
|
||||
.attach('file', fileBuffer, 'export.ndjson')
|
||||
.expect(200)
|
||||
.then((resp) => {
|
||||
expect(resp.body).to.eql({
|
||||
successCount: 1,
|
||||
success: true,
|
||||
warnings: [],
|
||||
successResults: [
|
||||
{
|
||||
type: 'test-hidden-importable-exportable',
|
||||
id: 'some-id-1',
|
||||
meta: {
|
||||
title: 'my title',
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('does not import objects with non importableAndExportable type', async () => {
|
||||
const fileBuffer = Buffer.from(
|
||||
'{"id":"some-id-1","type":"test-hidden-non-importable-exportable","attributes":{"title":"my title"},"references":[]}',
|
||||
'utf8'
|
||||
);
|
||||
await supertest
|
||||
.post('/api/saved_objects/_import')
|
||||
.set('kbn-xsrf', 'true')
|
||||
.attach('file', fileBuffer, 'export.ndjson')
|
||||
.expect(200)
|
||||
.then((resp) => {
|
||||
expect(resp.body).to.eql({
|
||||
successCount: 0,
|
||||
success: false,
|
||||
warnings: [],
|
||||
errors: [
|
||||
{
|
||||
id: 'some-id-1',
|
||||
type: 'test-hidden-non-importable-exportable',
|
||||
title: 'my title',
|
||||
meta: {
|
||||
title: 'my title',
|
||||
},
|
||||
error: {
|
||||
type: 'unsupported_type',
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { PluginFunctionalProviderContext } from '../../services';
|
||||
|
||||
export default function ({ loadTestFile }: PluginFunctionalProviderContext) {
|
||||
describe('Saved objects with hidden type', function () {
|
||||
loadTestFile(require.resolve('./import'));
|
||||
loadTestFile(require.resolve('./export'));
|
||||
loadTestFile(require.resolve('./resolve_import_errors'));
|
||||
loadTestFile(require.resolve('./find'));
|
||||
loadTestFile(require.resolve('./delete'));
|
||||
loadTestFile(require.resolve('./interface/saved_objects_management'));
|
||||
});
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
{"attributes": { "title": "Hidden Saved object type that is importable/exportable." }, "id":"ff3733a0-9fty-11e7-ahb3-3dcb94193fab", "references":[], "type":"test-hidden-importable-exportable", "version":1}
|
|
@ -0,0 +1 @@
|
|||
{"attributes": { "title": "Hidden Saved object type that is not importable/exportable." },"id":"op3767a1-9rcg-53u7-jkb3-3dnb74193awc","references":[],"type":"test-hidden-non-importable-exportable","version":1}
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import path from 'path';
|
||||
import expect from '@kbn/expect';
|
||||
import { PluginFunctionalProviderContext } from '../../../services';
|
||||
|
||||
export default function ({ getPageObjects, getService }: PluginFunctionalProviderContext) {
|
||||
const PageObjects = getPageObjects(['common', 'settings', 'header', 'savedObjects']);
|
||||
const esArchiver = getService('esArchiver');
|
||||
const fixturePaths = {
|
||||
hiddenImportable: path.join(__dirname, 'exports', '_import_hidden_importable.ndjson'),
|
||||
hiddenNonImportable: path.join(__dirname, 'exports', '_import_hidden_non_importable.ndjson'),
|
||||
};
|
||||
|
||||
describe('Saved objects management Interface', () => {
|
||||
before(() => esArchiver.emptyKibanaIndex());
|
||||
beforeEach(async () => {
|
||||
await PageObjects.settings.navigateTo();
|
||||
await PageObjects.settings.clickKibanaSavedObjects();
|
||||
});
|
||||
describe('importable/exportable hidden type', () => {
|
||||
it('imports objects successfully', async () => {
|
||||
await PageObjects.savedObjects.importFile(fixturePaths.hiddenImportable);
|
||||
await PageObjects.savedObjects.checkImportSucceeded();
|
||||
});
|
||||
|
||||
it('shows test-hidden-importable-exportable in table', async () => {
|
||||
await PageObjects.savedObjects.searchForObject('type:(test-hidden-importable-exportable)');
|
||||
const results = await PageObjects.savedObjects.getTableSummary();
|
||||
expect(results.length).to.be(1);
|
||||
|
||||
const { title } = results[0];
|
||||
expect(title).to.be(
|
||||
'test-hidden-importable-exportable [id=ff3733a0-9fty-11e7-ahb3-3dcb94193fab]'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('non-importable/exportable hidden type', () => {
|
||||
it('fails to import object', async () => {
|
||||
await PageObjects.savedObjects.importFile(fixturePaths.hiddenNonImportable);
|
||||
await PageObjects.savedObjects.checkImportSucceeded();
|
||||
|
||||
const errorsCount = await PageObjects.savedObjects.getImportErrorsCount();
|
||||
expect(errorsCount).to.be(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import expect from '@kbn/expect';
|
||||
import { PluginFunctionalProviderContext } from '../../services';
|
||||
|
||||
export default function ({ getService }: PluginFunctionalProviderContext) {
|
||||
const supertest = getService('supertest');
|
||||
const esArchiver = getService('esArchiver');
|
||||
|
||||
describe('export', () => {
|
||||
before(() =>
|
||||
esArchiver.load(
|
||||
'../functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects'
|
||||
)
|
||||
);
|
||||
after(() =>
|
||||
esArchiver.unload(
|
||||
'../functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects'
|
||||
)
|
||||
);
|
||||
|
||||
it('resolves objects with importableAndExportable types', async () => {
|
||||
const fileBuffer = Buffer.from(
|
||||
'{"id":"ff3733a0-9fty-11e7-ahb3-3dcb94193fab","type":"test-hidden-importable-exportable","attributes":{"title":"new title!"},"references":[]}',
|
||||
'utf8'
|
||||
);
|
||||
|
||||
await supertest
|
||||
.post('/api/saved_objects/_resolve_import_errors')
|
||||
.set('kbn-xsrf', 'true')
|
||||
.field(
|
||||
'retries',
|
||||
JSON.stringify([
|
||||
{
|
||||
id: 'ff3733a0-9fty-11e7-ahb3-3dcb94193fab',
|
||||
type: 'test-hidden-importable-exportable',
|
||||
overwrite: true,
|
||||
},
|
||||
])
|
||||
)
|
||||
.attach('file', fileBuffer, 'import.ndjson')
|
||||
.expect(200)
|
||||
.then((resp) => {
|
||||
expect(resp.body).to.eql({
|
||||
successCount: 1,
|
||||
success: true,
|
||||
warnings: [],
|
||||
successResults: [
|
||||
{
|
||||
type: 'test-hidden-importable-exportable',
|
||||
id: 'ff3733a0-9fty-11e7-ahb3-3dcb94193fab',
|
||||
meta: {
|
||||
title: 'new title!',
|
||||
},
|
||||
overwrite: true,
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('rejects objects with non importableAndExportable types', async () => {
|
||||
const fileBuffer = Buffer.from(
|
||||
'{"id":"op3767a1-9rcg-53u7-jkb3-3dnb74193awc","type":"test-hidden-non-importable-exportable","attributes":{"title":"new title!"},"references":[]}',
|
||||
'utf8'
|
||||
);
|
||||
|
||||
await supertest
|
||||
.post('/api/saved_objects/_resolve_import_errors')
|
||||
.set('kbn-xsrf', 'true')
|
||||
.field(
|
||||
'retries',
|
||||
JSON.stringify([
|
||||
{
|
||||
id: 'op3767a1-9rcg-53u7-jkb3-3dnb74193awc',
|
||||
type: 'test-hidden-non-importable-exportable',
|
||||
overwrite: true,
|
||||
},
|
||||
])
|
||||
)
|
||||
.attach('file', fileBuffer, 'import.ndjson')
|
||||
.expect(200)
|
||||
.then((resp) => {
|
||||
expect(resp.body).to.eql({
|
||||
successCount: 0,
|
||||
success: false,
|
||||
warnings: [],
|
||||
errors: [
|
||||
{
|
||||
id: 'op3767a1-9rcg-53u7-jkb3-3dnb74193awc',
|
||||
type: 'test-hidden-non-importable-exportable',
|
||||
title: 'new title!',
|
||||
meta: {
|
||||
title: 'new title!',
|
||||
},
|
||||
error: {
|
||||
type: 'unsupported_type',
|
||||
},
|
||||
overwrite: true,
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import expect from '@kbn/expect';
|
||||
import { PluginFunctionalProviderContext } from '../../services';
|
||||
|
||||
export default function ({ getService }: PluginFunctionalProviderContext) {
|
||||
const supertest = getService('supertest');
|
||||
const esArchiver = getService('esArchiver');
|
||||
|
||||
describe('find', () => {
|
||||
describe('saved objects with hidden type', () => {
|
||||
before(() =>
|
||||
esArchiver.load(
|
||||
'../functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects'
|
||||
)
|
||||
);
|
||||
after(() =>
|
||||
esArchiver.unload(
|
||||
'../functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects'
|
||||
)
|
||||
);
|
||||
it('returns saved objects with importableAndExportable types', async () =>
|
||||
await supertest
|
||||
.get(
|
||||
'/api/kibana/management/saved_objects/_find?type=test-hidden-importable-exportable&fields=title'
|
||||
)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.expect(200)
|
||||
.then((resp) => {
|
||||
expect(resp.body).to.eql({
|
||||
page: 1,
|
||||
per_page: 20,
|
||||
total: 1,
|
||||
saved_objects: [
|
||||
{
|
||||
type: 'test-hidden-importable-exportable',
|
||||
id: 'ff3733a0-9fty-11e7-ahb3-3dcb94193fab',
|
||||
attributes: {
|
||||
title: 'Hidden Saved object type that is importable/exportable.',
|
||||
},
|
||||
references: [],
|
||||
updated_at: '2021-02-11T18:51:23.794Z',
|
||||
version: 'WzIsMl0=',
|
||||
namespaces: ['default'],
|
||||
score: 0,
|
||||
meta: {
|
||||
namespaceType: 'single',
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
}));
|
||||
|
||||
it('returns empty response for non importableAndExportable types', async () =>
|
||||
await supertest
|
||||
.get(
|
||||
'/api/kibana/management/saved_objects/_find?type=test-hidden-non-importable-exportable'
|
||||
)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.expect(200)
|
||||
.then((resp) => {
|
||||
expect(resp.body).to.eql({
|
||||
page: 1,
|
||||
per_page: 20,
|
||||
total: 0,
|
||||
saved_objects: [],
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import expect from '@kbn/expect';
|
||||
import { PluginFunctionalProviderContext } from '../../services';
|
||||
|
||||
export default function ({ getService }: PluginFunctionalProviderContext) {
|
||||
const supertest = getService('supertest');
|
||||
const esArchiver = getService('esArchiver');
|
||||
|
||||
describe('get', () => {
|
||||
describe('saved objects with hidden type', () => {
|
||||
before(() =>
|
||||
esArchiver.load(
|
||||
'../functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects'
|
||||
)
|
||||
);
|
||||
after(() =>
|
||||
esArchiver.unload(
|
||||
'../functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects'
|
||||
)
|
||||
);
|
||||
const hiddenTypeExportableImportable =
|
||||
'test-hidden-importable-exportable/ff3733a0-9fty-11e7-ahb3-3dcb94193fab';
|
||||
const hiddenTypeNonExportableImportable =
|
||||
'test-hidden-non-importable-exportable/op3767a1-9rcg-53u7-jkb3-3dnb74193awc';
|
||||
|
||||
it('should return 200 for hidden types that are importableAndExportable', async () =>
|
||||
await supertest
|
||||
.get(`/api/kibana/management/saved_objects/${hiddenTypeExportableImportable}`)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.expect(200)
|
||||
.then((resp) => {
|
||||
const { body } = resp;
|
||||
const { type, id, meta } = body;
|
||||
expect(type).to.eql('test-hidden-importable-exportable');
|
||||
expect(id).to.eql('ff3733a0-9fty-11e7-ahb3-3dcb94193fab');
|
||||
expect(meta).to.not.equal(undefined);
|
||||
}));
|
||||
|
||||
it('should return 404 for hidden types that are not importableAndExportable', async () =>
|
||||
await supertest
|
||||
.get(`/api/kibana/management/saved_objects/${hiddenTypeNonExportableImportable}`)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.expect(404));
|
||||
});
|
||||
});
|
||||
}
|
|
@ -10,6 +10,9 @@ import { PluginFunctionalProviderContext } from '../../services';
|
|||
|
||||
export default function ({ loadTestFile }: PluginFunctionalProviderContext) {
|
||||
describe('Saved Objects Management', function () {
|
||||
loadTestFile(require.resolve('./find'));
|
||||
loadTestFile(require.resolve('./scroll_count'));
|
||||
loadTestFile(require.resolve('./get'));
|
||||
loadTestFile(require.resolve('./export_transform'));
|
||||
loadTestFile(require.resolve('./import_warnings'));
|
||||
});
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import expect from '@kbn/expect';
|
||||
import { PluginFunctionalProviderContext } from '../../services';
|
||||
|
||||
export default function ({ getService }: PluginFunctionalProviderContext) {
|
||||
const supertest = getService('supertest');
|
||||
const esArchiver = getService('esArchiver');
|
||||
const apiUrl = '/api/kibana/management/saved_objects/scroll/counts';
|
||||
|
||||
describe('scroll_count', () => {
|
||||
describe('saved objects with hidden type', () => {
|
||||
before(() =>
|
||||
esArchiver.load(
|
||||
'../functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects'
|
||||
)
|
||||
);
|
||||
after(() =>
|
||||
esArchiver.unload(
|
||||
'../functional/fixtures/es_archiver/saved_objects_management/hidden_saved_objects'
|
||||
)
|
||||
);
|
||||
|
||||
it('only counts hidden types that are importableAndExportable', async () => {
|
||||
const res = await supertest
|
||||
.post(apiUrl)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send({
|
||||
typesToInclude: [
|
||||
'test-hidden-non-importable-exportable',
|
||||
'test-hidden-importable-exportable',
|
||||
],
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
expect(res.body).to.eql({
|
||||
'test-hidden-importable-exportable': 1,
|
||||
'test-hidden-non-importable-exportable': 0,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue