diff --git a/src/plugins/data/public/index_patterns/index_patterns/index_pattern.ts b/src/plugins/data/public/index_patterns/index_patterns/index_pattern.ts
index 98ec4495cef29ac..f3297f21c572a5a 100644
--- a/src/plugins/data/public/index_patterns/index_patterns/index_pattern.ts
+++ b/src/plugins/data/public/index_patterns/index_patterns/index_pattern.ts
@@ -299,6 +299,13 @@ export class IndexPattern implements IIndexPattern {
}
async popularizeField(fieldName: string, unit = 1) {
+ /**
+ * This function is just used by Discover and it's high likely to be removed in the near future
+ * It doesn't use the save function to skip the error message that's displayed when
+ * a user adds several columns in a higher frequency that the changes can be persisted to ES
+ * resulting in 409 errors
+ */
+ if (!this.id) return;
const field = this.fields.getByName(fieldName);
if (!field) {
return;
@@ -308,7 +315,15 @@ export class IndexPattern implements IIndexPattern {
return;
}
field.count = count;
- await this.save();
+
+ try {
+ const res = await this.savedObjectsClient.update(type, this.id, this.prepBody(), {
+ version: this.version,
+ });
+ this.version = res._version;
+ } catch (e) {
+ // no need for an error message here
+ }
}
getNonScriptedFields() {
diff --git a/test/functional/apps/visualize/_tsvb_chart.ts b/test/functional/apps/visualize/_tsvb_chart.ts
index 333aa93b7776daa..e9cf8235ff3f4cf 100644
--- a/test/functional/apps/visualize/_tsvb_chart.ts
+++ b/test/functional/apps/visualize/_tsvb_chart.ts
@@ -28,7 +28,8 @@ export default function({ getService, getPageObjects }: FtrProviderContext) {
const security = getService('security');
const PageObjects = getPageObjects(['visualize', 'visualBuilder', 'timePicker', 'visChart']);
- describe('visual builder', function describeIndexTests() {
+ // FLAKY: https://github.com/elastic/kibana/issues/43150
+ describe.skip('visual builder', function describeIndexTests() {
this.tags('includeFirefox');
beforeEach(async () => {
await security.testUser.setRoles(['kibana_admin', 'test_logstash_reader']);
diff --git a/x-pack/plugins/apm/public/application/index.tsx b/x-pack/plugins/apm/public/application/index.tsx
index 314bd722274debb..6c1c3d3262a0ef7 100644
--- a/x-pack/plugins/apm/public/application/index.tsx
+++ b/x-pack/plugins/apm/public/application/index.tsx
@@ -24,7 +24,7 @@ import { UpdateBreadcrumbs } from '../components/app/Main/UpdateBreadcrumbs';
import { APMIndicesPermission } from '../components/app/APMIndicesPermission';
import { ScrollToTopOnPathChange } from '../components/app/Main/ScrollToTopOnPathChange';
import { routes } from '../components/app/Main/route_config';
-import { history } from '../utils/history';
+import { history, resetHistory } from '../utils/history';
import { ConfigSchema } from '..';
import 'react-vis/dist/style.css';
@@ -111,6 +111,7 @@ export const renderApp = (
{ element }: AppMountParameters,
config: ConfigSchema
) => {
+ resetHistory();
ReactDOM.render(
,
element
);
- return () => ReactDOM.unmountComponentAtNode(element);
+ return () => {
+ ReactDOM.unmountComponentAtNode(element);
+ };
};
diff --git a/x-pack/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/sections.ts b/x-pack/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/sections.ts
index 1eeebc8543d72f5..2c0d73f68760ded 100644
--- a/x-pack/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/sections.ts
+++ b/x-pack/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/sections.ts
@@ -16,11 +16,15 @@ import {
AGENT,
URL,
USER,
- CUSTOM_ERROR
+ CUSTOM_ERROR,
+ TRACE,
+ TRANSACTION
} from '../sections';
export const ERROR_METADATA_SECTIONS: Section[] = [
{ ...LABELS, required: true },
+ TRACE,
+ TRANSACTION,
ERROR,
HTTP,
HOST,
diff --git a/x-pack/plugins/apm/public/components/shared/MetadataTable/SpanMetadata/sections.ts b/x-pack/plugins/apm/public/components/shared/MetadataTable/SpanMetadata/sections.ts
index 5a83a9bf4ef9e14..f8d14707f164dfc 100644
--- a/x-pack/plugins/apm/public/components/shared/MetadataTable/SpanMetadata/sections.ts
+++ b/x-pack/plugins/apm/public/components/shared/MetadataTable/SpanMetadata/sections.ts
@@ -17,9 +17,9 @@ import {
export const SPAN_METADATA_SECTIONS: Section[] = [
LABELS,
- SPAN,
- TRANSACTION,
TRACE,
+ TRANSACTION,
+ SPAN,
SERVICE,
MESSAGE_SPAN,
AGENT
diff --git a/x-pack/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/sections.ts b/x-pack/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/sections.ts
index 3a9a21356ba35a0..69d934e588e9d47 100644
--- a/x-pack/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/sections.ts
+++ b/x-pack/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/sections.ts
@@ -20,11 +20,13 @@ import {
USER,
USER_AGENT,
CUSTOM_TRANSACTION,
- MESSAGE_TRANSACTION
+ MESSAGE_TRANSACTION,
+ TRACE
} from '../sections';
export const TRANSACTION_METADATA_SECTIONS: Section[] = [
{ ...LABELS, required: true },
+ TRACE,
TRANSACTION,
HTTP,
HOST,
diff --git a/x-pack/plugins/apm/public/components/shared/MetadataTable/sections.ts b/x-pack/plugins/apm/public/components/shared/MetadataTable/sections.ts
index d6c0a72b8bb0846..a41651a454b3504 100644
--- a/x-pack/plugins/apm/public/components/shared/MetadataTable/sections.ts
+++ b/x-pack/plugins/apm/public/components/shared/MetadataTable/sections.ts
@@ -118,7 +118,8 @@ export const TRACE: Section = {
key: 'trace',
label: i18n.translate('xpack.apm.metadataTable.section.traceLabel', {
defaultMessage: 'Trace'
- })
+ }),
+ properties: ['id']
};
export const ERROR: Section = {
diff --git a/x-pack/plugins/apm/public/utils/history.ts b/x-pack/plugins/apm/public/utils/history.ts
index 1fd62341393c970..bd2203fe9206687 100644
--- a/x-pack/plugins/apm/public/utils/history.ts
+++ b/x-pack/plugins/apm/public/utils/history.ts
@@ -8,6 +8,10 @@ import { createHashHistory } from 'history';
// Make history singleton available across APM project
// TODO: Explore using React context or hook instead?
-const history = createHashHistory();
+let history = createHashHistory();
+
+export const resetHistory = () => {
+ history = createHashHistory();
+};
export { history };
diff --git a/x-pack/plugins/apm/server/routes/services.ts b/x-pack/plugins/apm/server/routes/services.ts
index 474ab1c6082a44c..782f8957cf188b8 100644
--- a/x-pack/plugins/apm/server/routes/services.ts
+++ b/x-pack/plugins/apm/server/routes/services.ts
@@ -7,7 +7,6 @@
import * as t from 'io-ts';
import Boom from 'boom';
import { unique } from 'lodash';
-import { ScopedAnnotationsClient } from '../../../observability/server';
import { setupRequest } from '../lib/helpers/setup_request';
import { getServiceAgentName } from '../lib/services/get_service_agent_name';
import { getServices } from '../lib/services/get_services';
@@ -95,13 +94,10 @@ export const serviceAnnotationsRoute = createRoute(() => ({
const { serviceName } = context.params.path;
const { environment } = context.params.query;
- let annotationsClient: ScopedAnnotationsClient | undefined;
-
- if (context.plugins.observability) {
- annotationsClient = await context.plugins.observability.getScopedAnnotationsClient(
- request
- );
- }
+ const annotationsClient = await context.plugins.observability?.getScopedAnnotationsClient(
+ context,
+ request
+ );
return getServiceAnnotations({
setup,
@@ -143,6 +139,7 @@ export const serviceAnnotationsCreateRoute = createRoute(() => ({
},
handler: async ({ request, context }) => {
const annotationsClient = await context.plugins.observability?.getScopedAnnotationsClient(
+ context,
request
);
diff --git a/x-pack/plugins/ingest_manager/common/types/models/epm.ts b/x-pack/plugins/ingest_manager/common/types/models/epm.ts
index 82de90e4735f260..cc9e23dc9388f6f 100644
--- a/x-pack/plugins/ingest_manager/common/types/models/epm.ts
+++ b/x-pack/plugins/ingest_manager/common/types/models/epm.ts
@@ -276,6 +276,9 @@ export interface IndexTemplate {
mappings: object;
aliases: object;
};
+ data_stream: {
+ timestamp_field: string;
+ };
}
export interface TemplateRef {
diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/__snapshots__/template.test.ts.snap b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/__snapshots__/template.test.ts.snap
index 440060aff961693..b1212cf3a6535bf 100644
--- a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/__snapshots__/template.test.ts.snap
+++ b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/__snapshots__/template.test.ts.snap
@@ -90,6 +90,9 @@ exports[`tests loading base.yml: base.yml 1`] = `
}
},
"aliases": {}
+ },
+ "data_stream": {
+ "timestamp_field": "@timestamp"
}
}
`;
@@ -184,6 +187,9 @@ exports[`tests loading coredns.logs.yml: coredns.logs.yml 1`] = `
}
},
"aliases": {}
+ },
+ "data_stream": {
+ "timestamp_field": "@timestamp"
}
}
`;
@@ -1662,6 +1668,9 @@ exports[`tests loading system.yml: system.yml 1`] = `
}
},
"aliases": {}
+ },
+ "data_stream": {
+ "timestamp_field": "@timestamp"
}
}
`;
diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/template.ts b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/template.ts
index c45c7e706be588d..65b5ae636612cff 100644
--- a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/template.ts
+++ b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/template.ts
@@ -294,6 +294,9 @@ function getBaseTemplate(
// To be filled with the aliases that we need
aliases: {},
},
+ data_stream: {
+ timestamp_field: '@timestamp',
+ },
};
}
diff --git a/x-pack/plugins/lens/public/app_plugin/app.test.tsx b/x-pack/plugins/lens/public/app_plugin/app.test.tsx
index 7dc39225f780f6c..0608c978ad0dc2d 100644
--- a/x-pack/plugins/lens/public/app_plugin/app.test.tsx
+++ b/x-pack/plugins/lens/public/app_plugin/app.test.tsx
@@ -104,7 +104,12 @@ describe('Lens App', () => {
storage: Storage;
docId?: string;
docStorage: SavedObjectStore;
- redirectTo: (id?: string, returnToOrigin?: boolean, newlyCreated?: boolean) => void;
+ redirectTo: (
+ id?: string,
+ returnToOrigin?: boolean,
+ originatingApp?: string | undefined,
+ newlyCreated?: boolean
+ ) => void;
originatingApp: string | undefined;
}> {
return ({
@@ -140,7 +145,14 @@ describe('Lens App', () => {
load: jest.fn(),
save: jest.fn(),
},
- redirectTo: jest.fn((id?: string, returnToOrigin?: boolean, newlyCreated?: boolean) => {}),
+ redirectTo: jest.fn(
+ (
+ id?: string,
+ returnToOrigin?: boolean,
+ originatingApp?: string | undefined,
+ newlyCreated?: boolean
+ ) => {}
+ ),
} as unknown) as jest.Mocked<{
navigation: typeof navigationStartMock;
editorFrame: EditorFrameInstance;
@@ -149,7 +161,12 @@ describe('Lens App', () => {
storage: Storage;
docId?: string;
docStorage: SavedObjectStore;
- redirectTo: (id?: string, returnToOrigin?: boolean, newlyCreated?: boolean) => void;
+ redirectTo: (
+ id?: string,
+ returnToOrigin?: boolean,
+ originatingApp?: string | undefined,
+ newlyCreated?: boolean
+ ) => void;
originatingApp: string | undefined;
}>;
}
@@ -348,7 +365,12 @@ describe('Lens App', () => {
storage: Storage;
docId?: string;
docStorage: SavedObjectStore;
- redirectTo: (id?: string, returnToOrigin?: boolean, newlyCreated?: boolean) => void;
+ redirectTo: (
+ id?: string,
+ returnToOrigin?: boolean,
+ originatingApp?: string | undefined,
+ newlyCreated?: boolean
+ ) => void;
originatingApp: string | undefined;
}>;
@@ -521,7 +543,7 @@ describe('Lens App', () => {
expression: 'kibana 3',
});
- expect(args.redirectTo).toHaveBeenCalledWith('aaa', undefined, true);
+ expect(args.redirectTo).toHaveBeenCalledWith('aaa', undefined, undefined, true);
inst.setProps({ docId: 'aaa' });
@@ -541,7 +563,7 @@ describe('Lens App', () => {
expression: 'kibana 3',
});
- expect(args.redirectTo).toHaveBeenCalledWith('aaa', undefined, true);
+ expect(args.redirectTo).toHaveBeenCalledWith('aaa', undefined, undefined, true);
inst.setProps({ docId: 'aaa' });
@@ -609,7 +631,7 @@ describe('Lens App', () => {
title: 'hello there',
});
- expect(args.redirectTo).toHaveBeenCalledWith('aaa', true, true);
+ expect(args.redirectTo).toHaveBeenCalledWith('aaa', true, undefined, true);
});
it('saves app filters and does not save pinned filters', async () => {
@@ -677,7 +699,12 @@ describe('Lens App', () => {
storage: Storage;
docId?: string;
docStorage: SavedObjectStore;
- redirectTo: (id?: string, returnToOrigin?: boolean, newlyCreated?: boolean) => void;
+ redirectTo: (
+ id?: string,
+ returnToOrigin?: boolean,
+ originatingApp?: string | undefined,
+ newlyCreated?: boolean
+ ) => void;
}>;
beforeEach(() => {
diff --git a/x-pack/plugins/lens/public/app_plugin/app.tsx b/x-pack/plugins/lens/public/app_plugin/app.tsx
index 9d0df16c68555d3..718f49413a0821b 100644
--- a/x-pack/plugins/lens/public/app_plugin/app.tsx
+++ b/x-pack/plugins/lens/public/app_plugin/app.tsx
@@ -33,6 +33,7 @@ interface State {
isLoading: boolean;
isSaveModalVisible: boolean;
indexPatternsForTopNav: IndexPatternInstance[];
+ originatingApp: string | undefined;
persistedDoc?: Document;
lastKnownDoc?: Document;
@@ -54,7 +55,7 @@ export function App({
docId,
docStorage,
redirectTo,
- originatingApp,
+ originatingAppFromUrl,
navigation,
}: {
editorFrame: EditorFrameInstance;
@@ -64,8 +65,13 @@ export function App({
storage: IStorageWrapper;
docId?: string;
docStorage: SavedObjectStore;
- redirectTo: (id?: string, returnToOrigin?: boolean, newlyCreated?: boolean) => void;
- originatingApp?: string | undefined;
+ redirectTo: (
+ id?: string,
+ returnToOrigin?: boolean,
+ originatingApp?: string | undefined,
+ newlyCreated?: boolean
+ ) => void;
+ originatingAppFromUrl?: string | undefined;
}) {
const language =
storage.get('kibana.userQueryLanguage') || core.uiSettings.get('search:queryLanguage');
@@ -77,6 +83,7 @@ export function App({
isSaveModalVisible: false,
indexPatternsForTopNav: [],
query: { query: '', language },
+ originatingApp: originatingAppFromUrl,
dateRange: {
fromDate: currentRange.from,
toDate: currentRange.to,
@@ -229,7 +236,7 @@ export function App({
lastKnownDoc: newDoc,
}));
if (docId !== id || saveProps.returnToOrigin) {
- redirectTo(id, saveProps.returnToOrigin, newlyCreated);
+ redirectTo(id, saveProps.returnToOrigin, state.originatingApp, newlyCreated);
}
})
.catch(e => {
@@ -269,7 +276,7 @@ export function App({
{
if (isSaveable && lastKnownDoc) {
setState(s => ({ ...s, isSaveModalVisible: true }));
@@ -422,7 +429,7 @@ export function App({
{lastKnownDoc && state.isSaveModalVisible && (
runSave(props)}
onClose={() => setState(s => ({ ...s, isSaveModalVisible: false }))}
documentInfo={{
diff --git a/x-pack/plugins/lens/public/app_plugin/mounter.tsx b/x-pack/plugins/lens/public/app_plugin/mounter.tsx
index b49e6cf5ba7b98d..7c875935f6320e3 100644
--- a/x-pack/plugins/lens/public/app_plugin/mounter.tsx
+++ b/x-pack/plugins/lens/public/app_plugin/mounter.tsx
@@ -47,15 +47,11 @@ export async function mountApp(
);
const redirectTo = (
routeProps: RouteComponentProps<{ id?: string }>,
- originatingApp: string,
id?: string,
returnToOrigin?: boolean,
+ originatingApp?: string,
newlyCreated?: boolean
) => {
- if (!!originatingApp && !returnToOrigin) {
- removeQueryParam(routeProps.history, 'embeddableOriginatingApp');
- }
-
if (!id) {
routeProps.history.push('/');
} else if (!originatingApp) {
@@ -78,7 +74,10 @@ export async function mountApp(
const renderEditor = (routeProps: RouteComponentProps<{ id?: string }>) => {
trackUiEvent('loaded');
const urlParams = parse(routeProps.location.search) as Record;
- const originatingApp = urlParams.embeddableOriginatingApp;
+ const originatingAppFromUrl = urlParams.embeddableOriginatingApp;
+ if (urlParams.embeddableOriginatingApp) {
+ removeQueryParam(routeProps.history, 'embeddableOriginatingApp');
+ }
return (
- redirectTo(routeProps, originatingApp, id, returnToOrigin, newlyCreated)
+ redirectTo={(id, returnToOrigin, originatingApp, newlyCreated) =>
+ redirectTo(routeProps, id, returnToOrigin, originatingApp, newlyCreated)
}
- originatingApp={originatingApp}
+ originatingAppFromUrl={originatingAppFromUrl}
/>
);
};
diff --git a/x-pack/plugins/observability/kibana.json b/x-pack/plugins/observability/kibana.json
index 8e2cfe980039ce3..712a46f76bb7473 100644
--- a/x-pack/plugins/observability/kibana.json
+++ b/x-pack/plugins/observability/kibana.json
@@ -6,6 +6,9 @@
"xpack",
"observability"
],
+ "optionalPlugins": [
+ "licensing"
+ ],
"ui": true,
"server": true
}
diff --git a/x-pack/plugins/observability/server/lib/annotations/bootstrap_annotations.ts b/x-pack/plugins/observability/server/lib/annotations/bootstrap_annotations.ts
index 58639ef084ce650..6ea9f82d11ab919 100644
--- a/x-pack/plugins/observability/server/lib/annotations/bootstrap_annotations.ts
+++ b/x-pack/plugins/observability/server/lib/annotations/bootstrap_annotations.ts
@@ -3,7 +3,12 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
-import { CoreSetup, PluginInitializerContext, KibanaRequest } from 'kibana/server';
+import {
+ CoreSetup,
+ PluginInitializerContext,
+ KibanaRequest,
+ RequestHandlerContext,
+} from 'kibana/server';
import { PromiseReturnType } from '../../../typings/common';
import { createAnnotationsClient } from './create_annotations_client';
import { registerAnnotationAPIs } from './register_annotation_apis';
@@ -31,11 +36,12 @@ export async function bootstrapAnnotations({ index, core, context }: Params) {
});
return {
- getScopedAnnotationsClient: (request: KibanaRequest) => {
+ getScopedAnnotationsClient: (requestContext: RequestHandlerContext, request: KibanaRequest) => {
return createAnnotationsClient({
index,
apiCaller: core.elasticsearch.dataClient.asScoped(request).callAsCurrentUser,
logger,
+ license: requestContext.licensing?.license,
});
},
};
diff --git a/x-pack/plugins/observability/server/lib/annotations/create_annotations_client.ts b/x-pack/plugins/observability/server/lib/annotations/create_annotations_client.ts
index 3f2604468e17c5b..71b1a42b2000d98 100644
--- a/x-pack/plugins/observability/server/lib/annotations/create_annotations_client.ts
+++ b/x-pack/plugins/observability/server/lib/annotations/create_annotations_client.ts
@@ -7,6 +7,8 @@
import { APICaller, Logger } from 'kibana/server';
import * as t from 'io-ts';
import { Client } from 'elasticsearch';
+import Boom from 'boom';
+import { ILicense } from '../../../../licensing/server';
import {
createAnnotationRt,
deleteAnnotationRt,
@@ -40,8 +42,9 @@ export function createAnnotationsClient(params: {
index: string;
apiCaller: APICaller;
logger: Logger;
+ license?: ILicense;
}) {
- const { index, apiCaller, logger } = params;
+ const { index, apiCaller, logger, license } = params;
const initIndex = () =>
createOrUpdateIndex({
@@ -51,48 +54,59 @@ export function createAnnotationsClient(params: {
logger,
});
+ function ensureGoldLicense any>(fn: T): T {
+ return ((...args) => {
+ if (!license?.hasAtLeast('gold')) {
+ throw Boom.forbidden('Annotations require at least a gold license or a trial license.');
+ }
+ return fn(...args);
+ }) as T;
+ }
+
return {
get index() {
return index;
},
- create: async (
- createParams: CreateParams
- ): Promise<{ _id: string; _index: string; _source: Annotation }> => {
- const indexExists = await apiCaller('indices.exists', {
- index,
- });
+ create: ensureGoldLicense(
+ async (
+ createParams: CreateParams
+ ): Promise<{ _id: string; _index: string; _source: Annotation }> => {
+ const indexExists = await apiCaller('indices.exists', {
+ index,
+ });
- if (!indexExists) {
- await initIndex();
- }
+ if (!indexExists) {
+ await initIndex();
+ }
- const annotation = {
- ...createParams,
- event: {
- created: new Date().toISOString(),
- },
- };
+ const annotation = {
+ ...createParams,
+ event: {
+ created: new Date().toISOString(),
+ },
+ };
- const response = (await apiCaller('index', {
- index,
- body: annotation,
- refresh: 'wait_for',
- })) as IndexDocumentResponse;
+ const response = (await apiCaller('index', {
+ index,
+ body: annotation,
+ refresh: 'wait_for',
+ })) as IndexDocumentResponse;
- return apiCaller('get', {
- index,
- id: response._id,
- });
- },
- getById: async (getByIdParams: GetByIdParams) => {
+ return apiCaller('get', {
+ index,
+ id: response._id,
+ });
+ }
+ ),
+ getById: ensureGoldLicense(async (getByIdParams: GetByIdParams) => {
const { id } = getByIdParams;
return apiCaller('get', {
id,
index,
});
- },
- delete: async (deleteParams: DeleteParams) => {
+ }),
+ delete: ensureGoldLicense(async (deleteParams: DeleteParams) => {
const { id } = deleteParams;
const response = (await apiCaller('delete', {
@@ -101,6 +115,6 @@ export function createAnnotationsClient(params: {
refresh: 'wait_for',
})) as PromiseReturnType;
return response;
- },
+ }),
};
}
diff --git a/x-pack/plugins/observability/server/lib/annotations/register_annotation_apis.ts b/x-pack/plugins/observability/server/lib/annotations/register_annotation_apis.ts
index 3c29822acd6dd0f..21ebfcd6205e724 100644
--- a/x-pack/plugins/observability/server/lib/annotations/register_annotation_apis.ts
+++ b/x-pack/plugins/observability/server/lib/annotations/register_annotation_apis.ts
@@ -32,7 +32,7 @@ export function registerAnnotationAPIs({
handler: (params: { data: t.TypeOf; client: ScopedAnnotationsClient }) => Promise
): RequestHandler {
return async (...args: Parameters) => {
- const [, request, response] = args;
+ const [context, request, response] = args;
const rt = types;
@@ -56,16 +56,26 @@ export function registerAnnotationAPIs({
index,
apiCaller,
logger,
+ license: context.licensing?.license,
});
- const res = await handler({
- data: validation.right,
- client,
- });
+ try {
+ const res = await handler({
+ data: validation.right,
+ client,
+ });
- return response.ok({
- body: res,
- });
+ return response.ok({
+ body: res,
+ });
+ } catch (err) {
+ return response.custom({
+ statusCode: err.output?.statusCode ?? 500,
+ body: {
+ message: err.output?.payload?.message ?? 'An internal server error occured',
+ },
+ });
+ }
};
}
diff --git a/x-pack/plugins/uptime/server/lib/alerts/tls.ts b/x-pack/plugins/uptime/server/lib/alerts/tls.ts
index c4464ff57521805..6aa9d1aa3c6457a 100644
--- a/x-pack/plugins/uptime/server/lib/alerts/tls.ts
+++ b/x-pack/plugins/uptime/server/lib/alerts/tls.ts
@@ -12,12 +12,10 @@ import { updateState } from './common';
import { ACTION_GROUP_DEFINITIONS, DYNAMIC_SETTINGS_DEFAULTS } from '../../../common/constants';
import { Cert, CertResult } from '../../../common/runtime_types';
import { commonStateTranslations, tlsTranslations } from './translations';
+import { DEFAULT_FROM, DEFAULT_TO } from '../../rest_api/certs/certs';
const { TLS } = ACTION_GROUP_DEFINITIONS;
-const DEFAULT_FROM = 'now-1d';
-const DEFAULT_TO = 'now';
-const DEFAULT_INDEX = 0;
const DEFAULT_SIZE = 20;
interface TlsAlertState {
@@ -113,7 +111,7 @@ export const tlsAlertFactory: UptimeAlertTypeFactory = (_server, libs) => ({
dynamicSettings,
from: DEFAULT_FROM,
to: DEFAULT_TO,
- index: DEFAULT_INDEX,
+ index: 0,
size: DEFAULT_SIZE,
notValidAfter: `now+${dynamicSettings?.certExpirationThreshold ??
DYNAMIC_SETTINGS_DEFAULTS.certExpirationThreshold}d`,
diff --git a/x-pack/plugins/uptime/server/lib/requests/__tests__/get_certs.test.ts b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_certs.test.ts
index 689dce98859e152..5fa5c331d398e8c 100644
--- a/x-pack/plugins/uptime/server/lib/requests/__tests__/get_certs.test.ts
+++ b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_certs.test.ts
@@ -180,7 +180,7 @@ describe('getCerts', () => {
},
Object {
"range": Object {
- "@timestamp": Object {
+ "monitor.timespan": Object {
"gte": "now-2d",
"lte": "now+1h",
},
diff --git a/x-pack/plugins/uptime/server/lib/requests/get_certs.ts b/x-pack/plugins/uptime/server/lib/requests/get_certs.ts
index 57a59936ddf7c6b..4793d420cbfd838 100644
--- a/x-pack/plugins/uptime/server/lib/requests/get_certs.ts
+++ b/x-pack/plugins/uptime/server/lib/requests/get_certs.ts
@@ -51,7 +51,7 @@ export const getCerts: UMElasticsearchQueryFn = asyn
},
{
range: {
- '@timestamp': {
+ 'monitor.timespan': {
gte: from,
lte: to,
},
diff --git a/x-pack/plugins/uptime/server/rest_api/certs/certs.ts b/x-pack/plugins/uptime/server/rest_api/certs/certs.ts
index a5ca6e264d299f8..fb22d603a2d56e0 100644
--- a/x-pack/plugins/uptime/server/rest_api/certs/certs.ts
+++ b/x-pack/plugins/uptime/server/rest_api/certs/certs.ts
@@ -9,10 +9,10 @@ import { API_URLS } from '../../../common/constants';
import { UMServerLibs } from '../../lib/lib';
import { UMRestApiRouteFactory } from '../types';
-const DEFAULT_INDEX = 0;
+export const DEFAULT_FROM = 'now-5m';
+export const DEFAULT_TO = 'now';
+
const DEFAULT_SIZE = 25;
-const DEFAULT_FROM = 'now-1d';
-const DEFAULT_TO = 'now';
const DEFAULT_SORT = 'not_after';
const DEFAULT_DIRECTION = 'asc';
@@ -31,7 +31,7 @@ export const createGetCertsRoute: UMRestApiRouteFactory = (libs: UMServerLibs) =
}),
},
handler: async ({ callES, dynamicSettings }, _context, request, response): Promise => {
- const index = request.query?.index ?? DEFAULT_INDEX;
+ const index = request.query?.index ?? 0;
const size = request.query?.size ?? DEFAULT_SIZE;
const from = request.query?.from ?? DEFAULT_FROM;
const to = request.query?.to ?? DEFAULT_TO;
diff --git a/x-pack/scripts/functional_tests.js b/x-pack/scripts/functional_tests.js
index 3ec7776f848afd9..8ea554c42d6e0da 100644
--- a/x-pack/scripts/functional_tests.js
+++ b/x-pack/scripts/functional_tests.js
@@ -20,6 +20,8 @@ const onlyNotInCoverageTests = [
require.resolve('../test/alerting_api_integration/basic/config.ts'),
require.resolve('../test/alerting_api_integration/spaces_only/config.ts'),
require.resolve('../test/alerting_api_integration/security_and_spaces/config.ts'),
+ require.resolve('../test/apm_api_integration/basic/config.ts'),
+ require.resolve('../test/apm_api_integration/trial/config.ts'),
require.resolve('../test/detection_engine_api_integration/security_and_spaces/config.ts'),
require.resolve('../test/detection_engine_api_integration/basic/config.ts'),
require.resolve('../test/plugin_api_integration/config.ts'),
@@ -29,6 +31,8 @@ const onlyNotInCoverageTests = [
require.resolve('../test/token_api_integration/config.js'),
require.resolve('../test/oidc_api_integration/config.ts'),
require.resolve('../test/oidc_api_integration/implicit_flow.config.ts'),
+ require.resolve('../test/observability_api_integration/basic/config.ts'),
+ require.resolve('../test/observability_api_integration/trial/config.ts'),
require.resolve('../test/pki_api_integration/config.ts'),
require.resolve('../test/login_selector_api_integration/config.ts'),
require.resolve('../test/encrypted_saved_objects_api_integration/config.ts'),
diff --git a/x-pack/test/api_integration/apis/index.js b/x-pack/test/api_integration/apis/index.js
index 75fa90bb4c3fe84..321fbce52a75a5d 100644
--- a/x-pack/test/api_integration/apis/index.js
+++ b/x-pack/test/api_integration/apis/index.js
@@ -23,7 +23,6 @@ export default function({ loadTestFile }) {
loadTestFile(require.resolve('./management'));
loadTestFile(require.resolve('./uptime'));
loadTestFile(require.resolve('./maps'));
- loadTestFile(require.resolve('./apm'));
loadTestFile(require.resolve('./siem'));
loadTestFile(require.resolve('./short_urls'));
loadTestFile(require.resolve('./lens'));
@@ -31,6 +30,5 @@ export default function({ loadTestFile }) {
loadTestFile(require.resolve('./ingest'));
loadTestFile(require.resolve('./endpoint'));
loadTestFile(require.resolve('./ml'));
- loadTestFile(require.resolve('./observability'));
});
}
diff --git a/x-pack/test/api_integration/apis/uptime/rest/helper/make_ping.ts b/x-pack/test/api_integration/apis/uptime/rest/helper/make_ping.ts
index 908c571e07e0671..f9bea050293fc3b 100644
--- a/x-pack/test/api_integration/apis/uptime/rest/helper/make_ping.ts
+++ b/x-pack/test/api_integration/apis/uptime/rest/helper/make_ping.ts
@@ -18,6 +18,7 @@ export const makePing = async (
refresh: boolean = true,
tls: boolean | TlsProps = false
) => {
+ const timestamp = new Date();
const baseDoc: any = {
tcp: {
rtt: {
@@ -40,7 +41,7 @@ export const makePing = async (
ephemeral_id: '0d9a8dc6-f604-49e3-86a0-d8f9d6f2cbad',
version: '8.0.0',
},
- '@timestamp': new Date().toISOString(),
+ '@timestamp': timestamp.toISOString(),
resolve: {
rtt: {
us: 350,
@@ -88,6 +89,10 @@ export const makePing = async (
check_group: uuid.v4(),
type: 'http',
status: 'up',
+ timespan: {
+ gte: timestamp.toISOString(),
+ lt: new Date(timestamp.getTime() + 5000).toISOString,
+ },
},
event: {
dataset: 'uptime',
diff --git a/x-pack/test/api_integration/apis/uptime/rest/helper/make_tls.ts b/x-pack/test/api_integration/apis/uptime/rest/helper/make_tls.ts
index 360646252202451..477c9857ca36375 100644
--- a/x-pack/test/api_integration/apis/uptime/rest/helper/make_tls.ts
+++ b/x-pack/test/api_integration/apis/uptime/rest/helper/make_tls.ts
@@ -39,7 +39,7 @@ export const makeTls = ({ valid = true, commonName = '*.elastic.co', expiry, sha
server: {
x509: {
not_before: '2020-03-01T00:00:00.000Z',
- not_after: '2020-05-30T12:00:00.000Z',
+ not_after: expiryDate,
issuer: {
distinguished_name:
'CN=DigiCert SHA2 High Assurance Server CA,OU=www.digicert.com,O=DigiCert Inc,C=US',
diff --git a/x-pack/test/apm_api_integration/basic/config.ts b/x-pack/test/apm_api_integration/basic/config.ts
new file mode 100644
index 000000000000000..541fe9ec023bcfa
--- /dev/null
+++ b/x-pack/test/apm_api_integration/basic/config.ts
@@ -0,0 +1,14 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { createTestConfig } from '../common/config';
+
+// eslint-disable-next-line import/no-default-export
+export default createTestConfig({
+ license: 'basic',
+ name: 'X-Pack APM API integration tests (basic)',
+ testFiles: [require.resolve('./tests')],
+});
diff --git a/x-pack/test/api_integration/apis/apm/agent_configuration.ts b/x-pack/test/apm_api_integration/basic/tests/agent_configuration.ts
similarity index 98%
rename from x-pack/test/api_integration/apis/apm/agent_configuration.ts
rename to x-pack/test/apm_api_integration/basic/tests/agent_configuration.ts
index 8af648e062cf440..04974d57074a56d 100644
--- a/x-pack/test/api_integration/apis/apm/agent_configuration.ts
+++ b/x-pack/test/apm_api_integration/basic/tests/agent_configuration.ts
@@ -6,8 +6,9 @@
import expect from '@kbn/expect';
import { AgentConfigurationIntake } from '../../../../plugins/apm/common/agent_configuration/configuration_types';
-import { FtrProviderContext } from '../../ftr_provider_context';
+import { FtrProviderContext } from '../../common/ftr_provider_context';
+// eslint-disable-next-line import/no-default-export
export default function agentConfigurationTests({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
const log = getService('log');
diff --git a/x-pack/test/apm_api_integration/basic/tests/annotations.ts b/x-pack/test/apm_api_integration/basic/tests/annotations.ts
new file mode 100644
index 000000000000000..a939ef06273569c
--- /dev/null
+++ b/x-pack/test/apm_api_integration/basic/tests/annotations.ts
@@ -0,0 +1,52 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import expect from '@kbn/expect';
+import { JsonObject } from 'src/plugins/kibana_utils/common';
+import { FtrProviderContext } from '../../common/ftr_provider_context';
+
+// eslint-disable-next-line import/no-default-export
+export default function annotationApiTests({ getService }: FtrProviderContext) {
+ const supertest = getService('supertest');
+
+ function request({ method, url, data }: { method: string; url: string; data?: JsonObject }) {
+ switch (method.toLowerCase()) {
+ case 'post':
+ return supertest
+ .post(url)
+ .send(data)
+ .set('kbn-xsrf', 'foo');
+
+ default:
+ throw new Error(`Unsupported methoed ${method}`);
+ }
+ }
+
+ describe('APM annotations with a basic license', () => {
+ describe('when creating an annotation', () => {
+ it('fails with a 403 forbidden', async () => {
+ const response = await request({
+ url: '/api/apm/services/opbeans-java/annotation',
+ method: 'POST',
+ data: {
+ '@timestamp': new Date().toISOString(),
+ message: 'New deployment',
+ tags: ['foo'],
+ service: {
+ version: '1.1',
+ environment: 'production',
+ },
+ },
+ });
+
+ expect(response.status).to.be(403);
+ expect(response.body.message).to.be(
+ 'Annotations require at least a gold license or a trial license.'
+ );
+ });
+ });
+ });
+}
diff --git a/x-pack/test/api_integration/apis/apm/custom_link.ts b/x-pack/test/apm_api_integration/basic/tests/custom_link.ts
similarity index 96%
rename from x-pack/test/api_integration/apis/apm/custom_link.ts
rename to x-pack/test/apm_api_integration/basic/tests/custom_link.ts
index 8aefadd81177535..910c4797f39b76f 100644
--- a/x-pack/test/api_integration/apis/apm/custom_link.ts
+++ b/x-pack/test/apm_api_integration/basic/tests/custom_link.ts
@@ -3,13 +3,12 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
-// import querystring from 'querystring';
-// import {isEmpty} from 'lodash'
import URL from 'url';
import expect from '@kbn/expect';
import { CustomLink } from '../../../../plugins/apm/common/custom_link/custom_link_types';
-import { FtrProviderContext } from '../../ftr_provider_context';
+import { FtrProviderContext } from '../../common/ftr_provider_context';
+// eslint-disable-next-line import/no-default-export
export default function customLinksTests({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
const log = getService('log');
diff --git a/x-pack/test/api_integration/apis/apm/feature_controls.ts b/x-pack/test/apm_api_integration/basic/tests/feature_controls.ts
similarity index 98%
rename from x-pack/test/api_integration/apis/apm/feature_controls.ts
rename to x-pack/test/apm_api_integration/basic/tests/feature_controls.ts
index 5f61c963a69aa0c..f3647c65106c926 100644
--- a/x-pack/test/api_integration/apis/apm/feature_controls.ts
+++ b/x-pack/test/apm_api_integration/basic/tests/feature_controls.ts
@@ -5,8 +5,9 @@
*/
import expect from '@kbn/expect';
-import { FtrProviderContext } from '../../ftr_provider_context';
+import { FtrProviderContext } from '../../common/ftr_provider_context';
+// eslint-disable-next-line import/no-default-export
export default function featureControlsTests({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
const supertestWithoutAuth = getService('supertestWithoutAuth');
diff --git a/x-pack/test/api_integration/apis/apm/index.ts b/x-pack/test/apm_api_integration/basic/tests/index.ts
similarity index 73%
rename from x-pack/test/api_integration/apis/apm/index.ts
rename to x-pack/test/apm_api_integration/basic/tests/index.ts
index de076e8c46729ea..f3c1a3c3f63d56d 100644
--- a/x-pack/test/api_integration/apis/apm/index.ts
+++ b/x-pack/test/apm_api_integration/basic/tests/index.ts
@@ -3,11 +3,13 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
+import { FtrProviderContext } from '../../common/ftr_provider_context';
-import { FtrProviderContext } from '../../ftr_provider_context';
-
+// eslint-disable-next-line import/no-default-export
export default function apmApiIntegrationTests({ loadTestFile }: FtrProviderContext) {
- describe('APM specs', () => {
+ describe('APM specs (basic)', function() {
+ this.tags('ciGroup1');
+
loadTestFile(require.resolve('./annotations'));
loadTestFile(require.resolve('./feature_controls'));
loadTestFile(require.resolve('./agent_configuration'));
diff --git a/x-pack/test/apm_api_integration/common/config.ts b/x-pack/test/apm_api_integration/common/config.ts
new file mode 100644
index 000000000000000..9e011a98bbfcd48
--- /dev/null
+++ b/x-pack/test/apm_api_integration/common/config.ts
@@ -0,0 +1,38 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { FtrConfigProviderContext } from '@kbn/test/types/ftr';
+
+interface Settings {
+ license: 'basic' | 'trial';
+ testFiles: string[];
+ name: string;
+}
+
+export function createTestConfig(settings: Settings) {
+ const { testFiles, license, name } = settings;
+
+ return async ({ readConfigFile }: FtrConfigProviderContext) => {
+ const xPackAPITestsConfig = await readConfigFile(
+ require.resolve('../../api_integration/config.js')
+ );
+
+ return {
+ testFiles,
+ servers: xPackAPITestsConfig.get('servers'),
+ services: xPackAPITestsConfig.get('services'),
+ junit: {
+ reportName: name,
+ },
+
+ esTestCluster: {
+ ...xPackAPITestsConfig.get('esTestCluster'),
+ license,
+ },
+ kbnTestServer: xPackAPITestsConfig.get('kbnTestServer'),
+ };
+ };
+}
diff --git a/x-pack/test/apm_api_integration/common/ftr_provider_context.ts b/x-pack/test/apm_api_integration/common/ftr_provider_context.ts
new file mode 100644
index 000000000000000..90600816d171149
--- /dev/null
+++ b/x-pack/test/apm_api_integration/common/ftr_provider_context.ts
@@ -0,0 +1,7 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { FtrProviderContext } from '../../api_integration/ftr_provider_context';
diff --git a/x-pack/test/apm_api_integration/trial/config.ts b/x-pack/test/apm_api_integration/trial/config.ts
new file mode 100644
index 000000000000000..ca5b11d469c470c
--- /dev/null
+++ b/x-pack/test/apm_api_integration/trial/config.ts
@@ -0,0 +1,14 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { createTestConfig } from '../common/config';
+
+// eslint-disable-next-line import/no-default-export
+export default createTestConfig({
+ license: 'trial',
+ name: 'X-Pack APM API integration tests (trial)',
+ testFiles: [require.resolve('./tests')],
+});
diff --git a/x-pack/test/api_integration/apis/apm/annotations.ts b/x-pack/test/apm_api_integration/trial/tests/annotations.ts
similarity index 98%
rename from x-pack/test/api_integration/apis/apm/annotations.ts
rename to x-pack/test/apm_api_integration/trial/tests/annotations.ts
index 4746a7713f34b39..9beea6a53dd4d40 100644
--- a/x-pack/test/api_integration/apis/apm/annotations.ts
+++ b/x-pack/test/apm_api_integration/trial/tests/annotations.ts
@@ -7,10 +7,11 @@
import expect from '@kbn/expect';
import { merge, cloneDeep, isPlainObject } from 'lodash';
import { JsonObject } from 'src/plugins/kibana_utils/common';
-import { FtrProviderContext } from '../../ftr_provider_context';
+import { FtrProviderContext } from '../../common/ftr_provider_context';
const DEFAULT_INDEX_NAME = 'observability-annotations';
+// eslint-disable-next-line import/no-default-export
export default function annotationApiTests({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
const es = getService('es');
@@ -42,7 +43,7 @@ export default function annotationApiTests({ getService }: FtrProviderContext) {
}
}
- describe('APM annotations', () => {
+ describe('APM annotations with a trial license', () => {
describe('when creating an annotation', () => {
afterEach(async () => {
const indexExists = (await es.indices.exists({ index: DEFAULT_INDEX_NAME })).body;
diff --git a/x-pack/test/apm_api_integration/trial/tests/index.ts b/x-pack/test/apm_api_integration/trial/tests/index.ts
new file mode 100644
index 000000000000000..3a4571afb3d4a79
--- /dev/null
+++ b/x-pack/test/apm_api_integration/trial/tests/index.ts
@@ -0,0 +1,15 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { FtrProviderContext } from '../../../api_integration/ftr_provider_context';
+
+// eslint-disable-next-line import/no-default-export
+export default function observabilityApiIntegrationTests({ loadTestFile }: FtrProviderContext) {
+ describe('APM specs (trial)', function() {
+ this.tags('ciGroup1');
+ loadTestFile(require.resolve('./annotations'));
+ });
+}
diff --git a/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts b/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts
index b5946dcf22610b7..f36f26f61512517 100644
--- a/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts
+++ b/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts
@@ -60,10 +60,10 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
});
after(async () => {
+ await PageObjects.security.forceLogout();
await Promise.all([
security.role.delete('global_advanced_settings_all_role'),
security.user.delete('global_advanced_settings_all_user'),
- PageObjects.security.forceLogout(),
]);
});
diff --git a/x-pack/test/functional/apps/canvas/feature_controls/canvas_security.ts b/x-pack/test/functional/apps/canvas/feature_controls/canvas_security.ts
index 71c10bd8248be8e..57f198d204764a1 100644
--- a/x-pack/test/functional/apps/canvas/feature_controls/canvas_security.ts
+++ b/x-pack/test/functional/apps/canvas/feature_controls/canvas_security.ts
@@ -57,10 +57,10 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
});
after(async () => {
+ await PageObjects.security.forceLogout();
await Promise.all([
security.role.delete('global_canvas_all_role'),
security.user.delete('global_canvas_all_user'),
- PageObjects.security.forceLogout(),
]);
});
diff --git a/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_security.ts b/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_security.ts
index 25ef24f6bfd3932..008590c9c8dc1f0 100644
--- a/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_security.ts
+++ b/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_security.ts
@@ -62,10 +62,10 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
});
after(async () => {
+ await PageObjects.security.forceLogout();
await Promise.all([
security.role.delete('global_index_patterns_all_role'),
security.user.delete('global_index_patterns_all_user'),
- PageObjects.security.forceLogout(),
]);
});
diff --git a/x-pack/test/functional/apps/infra/feature_controls/infrastructure_security.ts b/x-pack/test/functional/apps/infra/feature_controls/infrastructure_security.ts
index ede77b7d9afa7f2..1520621312b08fb 100644
--- a/x-pack/test/functional/apps/infra/feature_controls/infrastructure_security.ts
+++ b/x-pack/test/functional/apps/infra/feature_controls/infrastructure_security.ts
@@ -52,10 +52,10 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
});
after(async () => {
+ await PageObjects.security.forceLogout();
await Promise.all([
security.role.delete('global_infrastructure_all_role'),
security.user.delete('global_infrastructure_all_user'),
- PageObjects.security.forceLogout(),
]);
});
@@ -168,10 +168,10 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
});
after(async () => {
+ await PageObjects.security.forceLogout();
await Promise.all([
security.role.delete('global_infrastructure_read_role'),
security.user.delete('global_infrastructure_read_user'),
- PageObjects.security.forceLogout(),
]);
});
diff --git a/x-pack/test/functional/apps/infra/feature_controls/logs_security.ts b/x-pack/test/functional/apps/infra/feature_controls/logs_security.ts
index 48ad4e90fd413f7..f53f60e5c7ea7af 100644
--- a/x-pack/test/functional/apps/infra/feature_controls/logs_security.ts
+++ b/x-pack/test/functional/apps/infra/feature_controls/logs_security.ts
@@ -49,10 +49,10 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
});
after(async () => {
+ await PageObjects.security.forceLogout();
await Promise.all([
security.role.delete('global_logs_all_role'),
security.user.delete('global_logs_all_user'),
- PageObjects.security.forceLogout(),
]);
});
@@ -112,10 +112,10 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
});
after(async () => {
+ await PageObjects.security.forceLogout();
await Promise.all([
security.role.delete('global_logs_read_role'),
security.user.delete('global_logs_read_user'),
- PageObjects.security.forceLogout(),
]);
});
@@ -175,10 +175,10 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
});
after(async () => {
+ await PageObjects.security.forceLogout();
await Promise.all([
security.role.delete('global_logs_no_privileges_role'),
security.user.delete('global_logs_no_privileges_user'),
- PageObjects.security.forceLogout(),
]);
});
diff --git a/x-pack/test/functional/apps/maps/feature_controls/maps_security.ts b/x-pack/test/functional/apps/maps/feature_controls/maps_security.ts
index ece162cbd96cc79..1651b118ea88ce3 100644
--- a/x-pack/test/functional/apps/maps/feature_controls/maps_security.ts
+++ b/x-pack/test/functional/apps/maps/feature_controls/maps_security.ts
@@ -57,10 +57,10 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
});
after(async () => {
+ await PageObjects.security.forceLogout();
await Promise.all([
security.role.delete('global_maps_all_role'),
security.user.delete('global_maps_all_user'),
- PageObjects.security.forceLogout(),
]);
});
diff --git a/x-pack/test/functional/apps/saved_objects_management/feature_controls/saved_objects_management_security.ts b/x-pack/test/functional/apps/saved_objects_management/feature_controls/saved_objects_management_security.ts
index d75540ae0b4a987..9fafaa6aae16b95 100644
--- a/x-pack/test/functional/apps/saved_objects_management/feature_controls/saved_objects_management_security.ts
+++ b/x-pack/test/functional/apps/saved_objects_management/feature_controls/saved_objects_management_security.ts
@@ -52,10 +52,10 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
});
after(async () => {
+ await PageObjects.security.forceLogout();
await Promise.all([
security.role.delete('global_all_role'),
security.user.delete('global_all_user'),
- PageObjects.security.forceLogout(),
]);
});
@@ -170,10 +170,10 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
});
after(async () => {
+ await PageObjects.security.forceLogout();
await Promise.all([
security.role.delete('global_som_read_role'),
security.user.delete('global_som_read_user'),
- PageObjects.security.forceLogout(),
]);
});
@@ -293,10 +293,10 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
});
after(async () => {
+ await PageObjects.security.forceLogout();
await Promise.all([
security.role.delete('global_visualize_all_role'),
security.user.delete('global_visualize_all_user'),
- PageObjects.security.forceLogout(),
]);
});
diff --git a/x-pack/test/functional/apps/uptime/certificates.ts b/x-pack/test/functional/apps/uptime/certificates.ts
index 93a8a852294b23a..4a10955637844ac 100644
--- a/x-pack/test/functional/apps/uptime/certificates.ts
+++ b/x-pack/test/functional/apps/uptime/certificates.ts
@@ -14,13 +14,9 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
const es = getService('es');
- // FLAKY: https://github.com/elastic/kibana/issues/65010
- describe.skip('certificate page', function() {
- before(async () => {
- await uptime.goToRoot(true);
- });
-
+ describe('certificates', function() {
beforeEach(async () => {
+ await uptime.goToRoot(true);
await makeCheck({ es, tls: true });
await uptimeService.navigation.refreshApp();
});
@@ -30,33 +26,39 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
await uptimeService.navigation.goToCertificates();
});
- it('displays certificates', async () => {
- await uptimeService.cert.hasCertificates();
- });
+ describe('page', () => {
+ beforeEach(async () => {
+ await uptimeService.navigation.goToCertificates();
+ });
- it('displays specific certificates', async () => {
- const certId = getSha256();
- const { monitorId } = await makeCheck({
- es,
- tls: {
- sha256: certId,
- },
+ it('displays certificates', async () => {
+ await uptimeService.cert.hasCertificates();
});
- await uptimeService.navigation.refreshApp();
- await uptimeService.cert.certificateExists({ certId, monitorId });
- });
+ it('displays specific certificates', async () => {
+ const certId = getSha256();
+ const { monitorId } = await makeCheck({
+ es,
+ tls: {
+ sha256: certId,
+ },
+ });
- it('performs search against monitor id', async () => {
- const certId = getSha256();
- const { monitorId } = await makeCheck({
- es,
- tls: {
- sha256: certId,
- },
+ await uptimeService.navigation.refreshApp();
+ await uptimeService.cert.certificateExists({ certId, monitorId });
+ });
+
+ it('performs search against monitor id', async () => {
+ const certId = getSha256();
+ const { monitorId } = await makeCheck({
+ es,
+ tls: {
+ sha256: certId,
+ },
+ });
+ await uptimeService.navigation.refreshApp();
+ await uptimeService.cert.searchIsWorking(monitorId);
});
- await uptimeService.navigation.refreshApp();
- await uptimeService.cert.searchIsWorking(monitorId);
});
});
};
diff --git a/x-pack/test/observability_api_integration/basic/config.ts b/x-pack/test/observability_api_integration/basic/config.ts
new file mode 100644
index 000000000000000..0e8bf1daaf9e613
--- /dev/null
+++ b/x-pack/test/observability_api_integration/basic/config.ts
@@ -0,0 +1,14 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { createTestConfig } from '../common/config';
+
+// eslint-disable-next-line import/no-default-export
+export default createTestConfig({
+ license: 'basic',
+ name: 'X-Pack Observability API integration tests (basic)',
+ testFiles: [require.resolve('./tests')],
+});
diff --git a/x-pack/test/observability_api_integration/basic/tests/annotations.ts b/x-pack/test/observability_api_integration/basic/tests/annotations.ts
new file mode 100644
index 000000000000000..cd86c8a0f2cda73
--- /dev/null
+++ b/x-pack/test/observability_api_integration/basic/tests/annotations.ts
@@ -0,0 +1,51 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import expect from '@kbn/expect';
+import { JsonObject } from 'src/plugins/kibana_utils/common';
+import { FtrProviderContext } from '../../common/ftr_provider_context';
+
+// eslint-disable-next-line import/no-default-export
+export default function annotationApiTests({ getService }: FtrProviderContext) {
+ const supertest = getService('supertest');
+
+ function request({ method, url, data }: { method: string; url: string; data?: JsonObject }) {
+ switch (method.toLowerCase()) {
+ case 'post':
+ return supertest
+ .post(url)
+ .send(data)
+ .set('kbn-xsrf', 'foo');
+
+ default:
+ throw new Error(`Unsupported methoed ${method}`);
+ }
+ }
+
+ describe('Observability annotations with a basic license', () => {
+ describe('when creating an annotation', () => {
+ it('fails with a 403 forbidden', async () => {
+ const response = await request({
+ url: '/api/observability/annotation',
+ method: 'POST',
+ data: {
+ annotation: {
+ type: 'deployment',
+ },
+ '@timestamp': new Date().toISOString(),
+ message: 'test message',
+ tags: ['apm'],
+ },
+ });
+
+ expect(response.status).to.be(403);
+ expect(response.body.message).to.be(
+ 'Annotations require at least a gold license or a trial license.'
+ );
+ });
+ });
+ });
+}
diff --git a/x-pack/test/observability_api_integration/basic/tests/index.ts b/x-pack/test/observability_api_integration/basic/tests/index.ts
new file mode 100644
index 000000000000000..a4c04a9229fa949
--- /dev/null
+++ b/x-pack/test/observability_api_integration/basic/tests/index.ts
@@ -0,0 +1,15 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { FtrProviderContext } from '../../common/ftr_provider_context';
+
+// eslint-disable-next-line import/no-default-export
+export default function observabilityApiIntegrationTests({ loadTestFile }: FtrProviderContext) {
+ describe('Observability specs (basic)', function() {
+ this.tags('ciGroup1');
+ loadTestFile(require.resolve('./annotations'));
+ });
+}
diff --git a/x-pack/test/observability_api_integration/common/config.ts b/x-pack/test/observability_api_integration/common/config.ts
new file mode 100644
index 000000000000000..9e011a98bbfcd48
--- /dev/null
+++ b/x-pack/test/observability_api_integration/common/config.ts
@@ -0,0 +1,38 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { FtrConfigProviderContext } from '@kbn/test/types/ftr';
+
+interface Settings {
+ license: 'basic' | 'trial';
+ testFiles: string[];
+ name: string;
+}
+
+export function createTestConfig(settings: Settings) {
+ const { testFiles, license, name } = settings;
+
+ return async ({ readConfigFile }: FtrConfigProviderContext) => {
+ const xPackAPITestsConfig = await readConfigFile(
+ require.resolve('../../api_integration/config.js')
+ );
+
+ return {
+ testFiles,
+ servers: xPackAPITestsConfig.get('servers'),
+ services: xPackAPITestsConfig.get('services'),
+ junit: {
+ reportName: name,
+ },
+
+ esTestCluster: {
+ ...xPackAPITestsConfig.get('esTestCluster'),
+ license,
+ },
+ kbnTestServer: xPackAPITestsConfig.get('kbnTestServer'),
+ };
+ };
+}
diff --git a/x-pack/test/observability_api_integration/common/ftr_provider_context.ts b/x-pack/test/observability_api_integration/common/ftr_provider_context.ts
new file mode 100644
index 000000000000000..90600816d171149
--- /dev/null
+++ b/x-pack/test/observability_api_integration/common/ftr_provider_context.ts
@@ -0,0 +1,7 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { FtrProviderContext } from '../../api_integration/ftr_provider_context';
diff --git a/x-pack/test/observability_api_integration/trial/config.ts b/x-pack/test/observability_api_integration/trial/config.ts
new file mode 100644
index 000000000000000..c073e2e6af7fed4
--- /dev/null
+++ b/x-pack/test/observability_api_integration/trial/config.ts
@@ -0,0 +1,14 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { createTestConfig } from '../common/config';
+
+// eslint-disable-next-line import/no-default-export
+export default createTestConfig({
+ license: 'trial',
+ name: 'X-Pack Observability API integration tests (trial)',
+ testFiles: [require.resolve('./tests')],
+});
diff --git a/x-pack/test/api_integration/apis/observability/annotations.ts b/x-pack/test/observability_api_integration/trial/tests/annotations.ts
similarity index 98%
rename from x-pack/test/api_integration/apis/observability/annotations.ts
rename to x-pack/test/observability_api_integration/trial/tests/annotations.ts
index 6d32162bfcc6581..ad3bcdbfabd8b3f 100644
--- a/x-pack/test/api_integration/apis/observability/annotations.ts
+++ b/x-pack/test/observability_api_integration/trial/tests/annotations.ts
@@ -8,10 +8,11 @@ import expect from '@kbn/expect';
import { JsonObject } from 'src/plugins/kibana_utils/common';
import { Annotation } from '../../../../plugins/observability/common/annotations';
import { ESSearchHit } from '../../../../plugins/apm/typings/elasticsearch';
-import { FtrProviderContext } from '../../ftr_provider_context';
+import { FtrProviderContext } from '../../common/ftr_provider_context';
const DEFAULT_INDEX_NAME = 'observability-annotations';
+// eslint-disable-next-line import/no-default-export
export default function annotationApiTests({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
const es = getService('es');
diff --git a/x-pack/test/observability_api_integration/trial/tests/index.ts b/x-pack/test/observability_api_integration/trial/tests/index.ts
new file mode 100644
index 000000000000000..d1acf4d98f7f977
--- /dev/null
+++ b/x-pack/test/observability_api_integration/trial/tests/index.ts
@@ -0,0 +1,15 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { FtrProviderContext } from '../../common/ftr_provider_context';
+
+// eslint-disable-next-line import/no-default-export
+export default function apmApiIntegrationTests({ loadTestFile }: FtrProviderContext) {
+ describe('Observability specs (trial)', function() {
+ this.tags('ciGroup1');
+ loadTestFile(require.resolve('./annotations'));
+ });
+}