mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[Obs AI Assistant] Use cookie auth for internal APIs in serverless tests (#203275)
## Summary ### Problem Cookie authentication was introduced in Kibana for serverless internal API tests via https://github.com/elastic/kibana/pull/192727. The serverless tests for Obs AI Assistant still uses API key based auth. ### Solution Change authentication to cookie based auth for internal APIs in serverless tests. ### Checklist Check the PR satisfies following conditions. Reviewers should verify this PR satisfies this list as well. - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [x] The PR description includes the appropriate Release Notes section, and the correct `release_note:*` label is applied per the [guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)
This commit is contained in:
parent
fdedae07b8
commit
7eb005242c
14 changed files with 184 additions and 282 deletions
|
@ -15,37 +15,47 @@ import supertest from 'supertest';
|
|||
import { Subtract } from 'utility-types';
|
||||
import { format } from 'url';
|
||||
import { Config } from '@kbn/test';
|
||||
import { SupertestWithRoleScope } from '@kbn/test-suites-xpack/api_integration/deployment_agnostic/services/role_scoped_supertest';
|
||||
import { InheritedFtrProviderContext } from '../../../../services';
|
||||
import type { InternalRequestHeader, RoleCredentials } from '../../../../../shared/services';
|
||||
|
||||
export function getObservabilityAIAssistantApiClient({
|
||||
svlSharedConfig,
|
||||
supertestUserWithCookieCredentials,
|
||||
}: {
|
||||
svlSharedConfig: Config;
|
||||
supertestUserWithCookieCredentials?: SupertestWithRoleScope;
|
||||
}) {
|
||||
const kibanaServer = svlSharedConfig.get('servers.kibana');
|
||||
const cAuthorities = svlSharedConfig.get('servers.kibana.certificateAuthorities');
|
||||
if (supertestUserWithCookieCredentials) {
|
||||
return createObservabilityAIAssistantApiClient(supertestUserWithCookieCredentials);
|
||||
} else {
|
||||
const kibanaServer = svlSharedConfig.get('servers.kibana');
|
||||
const cAuthorities = svlSharedConfig.get('servers.kibana.certificateAuthorities');
|
||||
|
||||
const url = format({
|
||||
...kibanaServer,
|
||||
auth: false, // don't use auth in serverless
|
||||
});
|
||||
|
||||
return createObservabilityAIAssistantApiClient(supertest.agent(url, { ca: cAuthorities }));
|
||||
const url = format({
|
||||
...kibanaServer,
|
||||
auth: false, // don't use auth in serverless
|
||||
});
|
||||
return createObservabilityAIAssistantApiClient(supertest.agent(url, { ca: cAuthorities }));
|
||||
}
|
||||
}
|
||||
|
||||
type ObservabilityAIAssistantApiClientKey = 'slsUser';
|
||||
type ObservabilityAIAssistantApiClientKey = 'slsAdmin' | 'slsEditor' | 'slsUser';
|
||||
|
||||
export type ObservabilityAIAssistantApiClient = Record<
|
||||
ObservabilityAIAssistantApiClientKey,
|
||||
Awaited<ReturnType<typeof getObservabilityAIAssistantApiClient>>
|
||||
>;
|
||||
export function createObservabilityAIAssistantApiClient(st: supertest.Agent) {
|
||||
|
||||
export function createObservabilityAIAssistantApiClient(
|
||||
st: SupertestWithRoleScope | supertest.Agent
|
||||
) {
|
||||
return <TEndpoint extends ObservabilityAIAssistantAPIEndpoint>(
|
||||
options: {
|
||||
type?: 'form-data';
|
||||
endpoint: TEndpoint;
|
||||
roleAuthc: RoleCredentials;
|
||||
internalReqHeader: InternalRequestHeader;
|
||||
roleAuthc?: RoleCredentials;
|
||||
internalReqHeader?: InternalRequestHeader;
|
||||
} & ObservabilityAIAssistantAPIClientRequestParamsOf<TEndpoint> & {
|
||||
params?: { query?: { _inspect?: boolean } };
|
||||
}
|
||||
|
@ -57,7 +67,8 @@ export function createObservabilityAIAssistantApiClient(st: supertest.Agent) {
|
|||
const { method, pathname, version } = formatRequest(endpoint, params.path);
|
||||
const url = format({ pathname, query: params?.query });
|
||||
|
||||
const headers: Record<string, string> = { ...internalReqHeader, ...roleAuthc.apiKeyHeader };
|
||||
const headers: Record<string, string> =
|
||||
roleAuthc && internalReqHeader ? { ...internalReqHeader, ...roleAuthc.apiKeyHeader } : {};
|
||||
|
||||
if (version) {
|
||||
headers['Elastic-Api-Version'] = version;
|
||||
|
@ -182,10 +193,34 @@ export async function getObservabilityAIAssistantApiClientService({
|
|||
getService,
|
||||
}: InheritedFtrProviderContext): Promise<ObservabilityAIAssistantApiClient> {
|
||||
const svlSharedConfig = getService('config');
|
||||
// defaults to elastic_admin user when used without auth
|
||||
const roleScopedSupertest = getService('roleScopedSupertest');
|
||||
|
||||
const supertestAdminWithCookieCredentials: SupertestWithRoleScope =
|
||||
await roleScopedSupertest.getSupertestWithRoleScope('admin', {
|
||||
useCookieHeader: true,
|
||||
withInternalHeaders: true,
|
||||
});
|
||||
|
||||
const supertestEditorWithCookieCredentials: SupertestWithRoleScope =
|
||||
await roleScopedSupertest.getSupertestWithRoleScope('editor', {
|
||||
useCookieHeader: true,
|
||||
withInternalHeaders: true,
|
||||
});
|
||||
|
||||
return {
|
||||
// defaults to elastic_admin user when used without auth
|
||||
slsUser: await getObservabilityAIAssistantApiClient({
|
||||
svlSharedConfig,
|
||||
}),
|
||||
// cookie auth for internal apis
|
||||
slsAdmin: await getObservabilityAIAssistantApiClient({
|
||||
svlSharedConfig,
|
||||
supertestUserWithCookieCredentials: supertestAdminWithCookieCredentials,
|
||||
}),
|
||||
// cookie auth for internal apis
|
||||
slsEditor: await getObservabilityAIAssistantApiClient({
|
||||
svlSharedConfig,
|
||||
supertestUserWithCookieCredentials: supertestEditorWithCookieCredentials,
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import {
|
|||
LlmProxy,
|
||||
createLlmProxy,
|
||||
} from '@kbn/test-suites-xpack/observability_ai_assistant_api_integration/common/create_llm_proxy';
|
||||
import { SupertestWithRoleScope } from '@kbn/test-suites-xpack/api_integration/deployment_agnostic/services/role_scoped_supertest';
|
||||
import { FtrProviderContext } from '../../common/ftr_provider_context';
|
||||
import { createProxyActionConnector, deleteActionConnector } from '../../common/action_connectors';
|
||||
import type { InternalRequestHeader, RoleCredentials } from '../../../../../../shared/services';
|
||||
|
@ -21,6 +22,9 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
const svlUserManager = getService('svlUserManager');
|
||||
const svlCommonApi = getService('svlCommonApi');
|
||||
const log = getService('log');
|
||||
const roleScopedSupertest = getService('roleScopedSupertest');
|
||||
|
||||
let supertestEditorWithCookieCredentials: SupertestWithRoleScope;
|
||||
|
||||
const CHAT_API_URL = `/internal/observability_ai_assistant/chat`;
|
||||
|
||||
|
@ -52,6 +56,15 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
before(async () => {
|
||||
roleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('editor');
|
||||
internalReqHeader = svlCommonApi.getInternalRequestHeader();
|
||||
|
||||
supertestEditorWithCookieCredentials = await roleScopedSupertest.getSupertestWithRoleScope(
|
||||
'editor',
|
||||
{
|
||||
useCookieHeader: true,
|
||||
withInternalHeaders: true,
|
||||
}
|
||||
);
|
||||
|
||||
proxy = await createLlmProxy(log);
|
||||
connectorId = await createProxyActionConnector({
|
||||
supertest: supertestWithoutAuth,
|
||||
|
@ -75,10 +88,8 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
});
|
||||
|
||||
it("returns a 4xx if the connector doesn't exist", async () => {
|
||||
await supertestWithoutAuth
|
||||
await supertestEditorWithCookieCredentials
|
||||
.post(CHAT_API_URL)
|
||||
.set(roleAuthc.apiKeyHeader)
|
||||
.set(internalReqHeader)
|
||||
.send({
|
||||
name: 'my_api_call',
|
||||
messages,
|
||||
|
@ -104,10 +115,8 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
const receivedChunks: Array<Record<string, any>> = [];
|
||||
|
||||
const passThrough = new PassThrough();
|
||||
supertestWithoutAuth
|
||||
supertestEditorWithCookieCredentials
|
||||
.post(CHAT_API_URL)
|
||||
.set(roleAuthc.apiKeyHeader)
|
||||
.set(internalReqHeader)
|
||||
.on('error', reject)
|
||||
.send({
|
||||
name: 'my_api_call',
|
||||
|
|
|
@ -25,6 +25,7 @@ import {
|
|||
LlmResponseSimulator,
|
||||
} from '@kbn/test-suites-xpack/observability_ai_assistant_api_integration/common/create_llm_proxy';
|
||||
import { createOpenAiChunk } from '@kbn/test-suites-xpack/observability_ai_assistant_api_integration/common/create_openai_chunk';
|
||||
import { SupertestWithRoleScope } from '@kbn/test-suites-xpack/api_integration/deployment_agnostic/services/role_scoped_supertest';
|
||||
import { FtrProviderContext } from '../../common/ftr_provider_context';
|
||||
import {
|
||||
decodeEvents,
|
||||
|
@ -39,6 +40,9 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
const log = getService('log');
|
||||
const svlUserManager = getService('svlUserManager');
|
||||
const svlCommonApi = getService('svlCommonApi');
|
||||
const roleScopedSupertest = getService('roleScopedSupertest');
|
||||
|
||||
let supertestEditorWithCookieCredentials: SupertestWithRoleScope;
|
||||
|
||||
const observabilityAIAssistantAPIClient = getService('observabilityAIAssistantAPIClient');
|
||||
|
||||
|
@ -82,10 +86,8 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
(body) => !isFunctionTitleRequest(body)
|
||||
);
|
||||
const responsePromise = new Promise<Response>((resolve, reject) => {
|
||||
supertestWithoutAuth
|
||||
supertestEditorWithCookieCredentials
|
||||
.post(COMPLETE_API_URL)
|
||||
.set(roleAuthc.apiKeyHeader)
|
||||
.set(internalReqHeader)
|
||||
.send({
|
||||
messages,
|
||||
connectorId,
|
||||
|
@ -134,6 +136,14 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
roleAuthc,
|
||||
internalReqHeader,
|
||||
});
|
||||
|
||||
supertestEditorWithCookieCredentials = await roleScopedSupertest.getSupertestWithRoleScope(
|
||||
'editor',
|
||||
{
|
||||
useCookieHeader: true,
|
||||
withInternalHeaders: true,
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
|
@ -155,10 +165,8 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
|
||||
const passThrough = new PassThrough();
|
||||
|
||||
supertestWithoutAuth
|
||||
supertestEditorWithCookieCredentials
|
||||
.post(COMPLETE_API_URL)
|
||||
.set(roleAuthc.apiKeyHeader)
|
||||
.set(internalReqHeader)
|
||||
.send({
|
||||
messages,
|
||||
connectorId,
|
||||
|
@ -254,6 +262,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
},
|
||||
});
|
||||
});
|
||||
|
||||
describe('when creating a new conversation', () => {
|
||||
let events: StreamingChatResponseEvent[];
|
||||
|
||||
|
@ -273,12 +282,14 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
content: 'Hello',
|
||||
},
|
||||
});
|
||||
|
||||
expect(omit(events[1], 'id')).to.eql({
|
||||
type: StreamingChatResponseEventType.ChatCompletionChunk,
|
||||
message: {
|
||||
content: ' again',
|
||||
},
|
||||
});
|
||||
|
||||
expect(omit(events[2], 'id', 'message.@timestamp')).to.eql({
|
||||
type: StreamingChatResponseEventType.ChatCompletionMessage,
|
||||
message: {
|
||||
|
@ -329,10 +340,8 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
)[0]?.conversation.id;
|
||||
|
||||
await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
.slsEditor({
|
||||
endpoint: 'DELETE /internal/observability_ai_assistant/conversation/{conversationId}',
|
||||
roleAuthc,
|
||||
internalReqHeader,
|
||||
params: {
|
||||
path: {
|
||||
conversationId: createdConversationId,
|
||||
|
@ -417,10 +426,8 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
).to.eql(0);
|
||||
|
||||
const conversations = await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
.slsEditor({
|
||||
endpoint: 'POST /internal/observability_ai_assistant/conversations',
|
||||
roleAuthc,
|
||||
internalReqHeader,
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
|
@ -449,10 +456,8 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
.completeAfterIntercept();
|
||||
|
||||
const createResponse = await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
.slsEditor({
|
||||
endpoint: 'POST /internal/observability_ai_assistant/chat/complete',
|
||||
roleAuthc,
|
||||
internalReqHeader,
|
||||
params: {
|
||||
body: {
|
||||
messages,
|
||||
|
@ -470,10 +475,8 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
conversationCreatedEvent = getConversationCreatedEvent(createResponse.body);
|
||||
|
||||
const conversationId = conversationCreatedEvent.conversation.id;
|
||||
const fullConversation = await observabilityAIAssistantAPIClient.slsUser({
|
||||
const fullConversation = await observabilityAIAssistantAPIClient.slsEditor({
|
||||
endpoint: 'GET /internal/observability_ai_assistant/conversation/{conversationId}',
|
||||
internalReqHeader,
|
||||
roleAuthc,
|
||||
params: {
|
||||
path: {
|
||||
conversationId,
|
||||
|
@ -486,10 +489,8 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
.completeAfterIntercept();
|
||||
|
||||
const updatedResponse = await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
.slsEditor({
|
||||
endpoint: 'POST /internal/observability_ai_assistant/chat/complete',
|
||||
internalReqHeader,
|
||||
roleAuthc,
|
||||
params: {
|
||||
body: {
|
||||
messages: [
|
||||
|
@ -519,10 +520,8 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
|
||||
after(async () => {
|
||||
await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
.slsEditor({
|
||||
endpoint: 'DELETE /internal/observability_ai_assistant/conversation/{conversationId}',
|
||||
internalReqHeader,
|
||||
roleAuthc,
|
||||
params: {
|
||||
path: {
|
||||
conversationId: conversationCreatedEvent.conversation.id,
|
||||
|
|
|
@ -63,8 +63,6 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
const responseBody = await invokeChatCompleteWithFunctionRequest({
|
||||
connectorId,
|
||||
observabilityAIAssistantAPIClient,
|
||||
internalReqHeader,
|
||||
roleAuthc,
|
||||
functionCall: {
|
||||
name: ELASTICSEARCH_FUNCTION_NAME,
|
||||
trigger: MessageRole.User,
|
||||
|
|
|
@ -13,7 +13,6 @@ import {
|
|||
} from '@kbn/observability-ai-assistant-plugin/common';
|
||||
import type { AssistantScope } from '@kbn/ai-assistant-common';
|
||||
import { Readable } from 'stream';
|
||||
import type { InternalRequestHeader, RoleCredentials } from '../../../../../../../shared/services';
|
||||
import { ObservabilityAIAssistantApiClient } from '../../../common/observability_ai_assistant_api_client';
|
||||
|
||||
function decodeEvents(body: Readable | string) {
|
||||
|
@ -34,22 +33,16 @@ export async function invokeChatCompleteWithFunctionRequest({
|
|||
connectorId,
|
||||
observabilityAIAssistantAPIClient,
|
||||
functionCall,
|
||||
roleAuthc,
|
||||
internalReqHeader,
|
||||
scopes,
|
||||
}: {
|
||||
connectorId: string;
|
||||
observabilityAIAssistantAPIClient: ObservabilityAIAssistantApiClient;
|
||||
functionCall: Message['message']['function_call'];
|
||||
scopes?: AssistantScope[];
|
||||
roleAuthc: RoleCredentials;
|
||||
internalReqHeader: InternalRequestHeader;
|
||||
}) {
|
||||
const { body } = await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
.slsEditor({
|
||||
endpoint: 'POST /internal/observability_ai_assistant/chat/complete',
|
||||
internalReqHeader,
|
||||
roleAuthc,
|
||||
params: {
|
||||
body: {
|
||||
messages: [
|
||||
|
|
|
@ -53,8 +53,6 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
await invokeChatCompleteWithFunctionRequest({
|
||||
connectorId,
|
||||
observabilityAIAssistantAPIClient,
|
||||
internalReqHeader,
|
||||
roleAuthc,
|
||||
functionCall: {
|
||||
name: 'summarize',
|
||||
trigger: MessageRole.User,
|
||||
|
@ -77,10 +75,8 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
});
|
||||
|
||||
it('persists entry in knowledge base', async () => {
|
||||
const res = await observabilityAIAssistantAPIClient.slsUser({
|
||||
const res = await observabilityAIAssistantAPIClient.slsEditor({
|
||||
endpoint: 'GET /internal/observability_ai_assistant/kb/entries',
|
||||
internalReqHeader,
|
||||
roleAuthc,
|
||||
params: {
|
||||
query: {
|
||||
query: '',
|
||||
|
|
|
@ -24,6 +24,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
describe('List connectors', () => {
|
||||
let roleAuthc: RoleCredentials;
|
||||
let internalReqHeader: InternalRequestHeader;
|
||||
|
||||
before(async () => {
|
||||
roleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('editor');
|
||||
internalReqHeader = svlCommonApi.getInternalRequestHeader();
|
||||
|
@ -45,19 +46,15 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
|
||||
it('Returns a 2xx for enterprise license', async () => {
|
||||
await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
.slsEditor({
|
||||
endpoint: 'GET /internal/observability_ai_assistant/connectors',
|
||||
roleAuthc,
|
||||
internalReqHeader,
|
||||
})
|
||||
.expect(200);
|
||||
});
|
||||
|
||||
it('returns an empty list of connectors', async () => {
|
||||
const res = await observabilityAIAssistantAPIClient.slsUser({
|
||||
const res = await observabilityAIAssistantAPIClient.slsEditor({
|
||||
endpoint: 'GET /internal/observability_ai_assistant/connectors',
|
||||
roleAuthc,
|
||||
internalReqHeader,
|
||||
});
|
||||
|
||||
expect(res.body.length).to.be(0);
|
||||
|
@ -72,10 +69,8 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
roleAuthc,
|
||||
});
|
||||
|
||||
const res = await observabilityAIAssistantAPIClient.slsUser({
|
||||
const res = await observabilityAIAssistantAPIClient.slsEditor({
|
||||
endpoint: 'GET /internal/observability_ai_assistant/connectors',
|
||||
internalReqHeader,
|
||||
roleAuthc,
|
||||
});
|
||||
|
||||
expect(res.body.length).to.be(1);
|
||||
|
|
|
@ -14,12 +14,9 @@ import {
|
|||
} from '@kbn/observability-ai-assistant-plugin/common/types';
|
||||
import type { FtrProviderContext } from '../../common/ftr_provider_context';
|
||||
import type { SupertestReturnType } from '../../common/observability_ai_assistant_api_client';
|
||||
import type { InternalRequestHeader, RoleCredentials } from '../../../../../../shared/services';
|
||||
|
||||
export default function ApiTest({ getService }: FtrProviderContext) {
|
||||
const observabilityAIAssistantAPIClient = getService('observabilityAIAssistantAPIClient');
|
||||
const svlUserManager = getService('svlUserManager');
|
||||
const svlCommonApi = getService('svlCommonApi');
|
||||
|
||||
const conversationCreate: ConversationCreateRequest = {
|
||||
'@timestamp': new Date().toISOString(),
|
||||
|
@ -48,22 +45,11 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
});
|
||||
|
||||
describe('Conversations', () => {
|
||||
let roleAuthc: RoleCredentials;
|
||||
let internalReqHeader: InternalRequestHeader;
|
||||
before(async () => {
|
||||
roleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('editor');
|
||||
internalReqHeader = svlCommonApi.getInternalRequestHeader();
|
||||
});
|
||||
after(async () => {
|
||||
await svlUserManager.invalidateM2mApiKeyWithRoleScope(roleAuthc);
|
||||
});
|
||||
describe('without conversations', () => {
|
||||
it('returns no conversations when listing', async () => {
|
||||
const response = await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
.slsEditor({
|
||||
endpoint: 'POST /internal/observability_ai_assistant/conversations',
|
||||
internalReqHeader,
|
||||
roleAuthc,
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
|
@ -72,10 +58,8 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
|
||||
it('returns a 404 for updating conversations', async () => {
|
||||
await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
.slsEditor({
|
||||
endpoint: 'PUT /internal/observability_ai_assistant/conversation/{conversationId}',
|
||||
internalReqHeader,
|
||||
roleAuthc,
|
||||
params: {
|
||||
path: {
|
||||
conversationId: 'non-existing-conversation-id',
|
||||
|
@ -90,10 +74,8 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
|
||||
it('returns a 404 for retrieving a conversation', async () => {
|
||||
await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
.slsEditor({
|
||||
endpoint: 'GET /internal/observability_ai_assistant/conversation/{conversationId}',
|
||||
internalReqHeader,
|
||||
roleAuthc,
|
||||
params: {
|
||||
path: {
|
||||
conversationId: 'my-conversation-id',
|
||||
|
@ -108,12 +90,11 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
let createResponse: Awaited<
|
||||
SupertestReturnType<'POST /internal/observability_ai_assistant/conversation'>
|
||||
>;
|
||||
|
||||
before(async () => {
|
||||
createResponse = await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
.slsEditor({
|
||||
endpoint: 'POST /internal/observability_ai_assistant/conversation',
|
||||
roleAuthc,
|
||||
internalReqHeader,
|
||||
params: {
|
||||
body: {
|
||||
conversation: conversationCreate,
|
||||
|
@ -125,10 +106,8 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
|
||||
after(async () => {
|
||||
await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
.slsEditor({
|
||||
endpoint: 'DELETE /internal/observability_ai_assistant/conversation/{conversationId}',
|
||||
internalReqHeader,
|
||||
roleAuthc,
|
||||
params: {
|
||||
path: {
|
||||
conversationId: createResponse.body.conversation.id,
|
||||
|
@ -138,10 +117,8 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
.expect(200);
|
||||
|
||||
await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
.slsEditor({
|
||||
endpoint: 'GET /internal/observability_ai_assistant/conversation/{conversationId}',
|
||||
internalReqHeader,
|
||||
roleAuthc,
|
||||
params: {
|
||||
path: {
|
||||
conversationId: createResponse.body.conversation.id,
|
||||
|
@ -150,6 +127,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('returns the conversation', function () {
|
||||
// delete user from response to avoid comparing it as it will be different in MKI
|
||||
delete createResponse.body.user;
|
||||
|
@ -170,10 +148,8 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
|
||||
it('returns a 404 for updating a non-existing conversation', async () => {
|
||||
await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
.slsEditor({
|
||||
endpoint: 'PUT /internal/observability_ai_assistant/conversation/{conversationId}',
|
||||
roleAuthc,
|
||||
internalReqHeader,
|
||||
params: {
|
||||
path: {
|
||||
conversationId: 'non-existing-conversation-id',
|
||||
|
@ -188,10 +164,8 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
|
||||
it('returns a 404 for retrieving a non-existing conversation', async () => {
|
||||
await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
.slsEditor({
|
||||
endpoint: 'GET /internal/observability_ai_assistant/conversation/{conversationId}',
|
||||
roleAuthc,
|
||||
internalReqHeader,
|
||||
params: {
|
||||
path: {
|
||||
conversationId: 'non-existing-conversation-id',
|
||||
|
@ -203,10 +177,8 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
|
||||
it('returns the conversation that was created', async () => {
|
||||
const response = await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
.slsEditor({
|
||||
endpoint: 'GET /internal/observability_ai_assistant/conversation/{conversationId}',
|
||||
internalReqHeader,
|
||||
roleAuthc,
|
||||
params: {
|
||||
path: {
|
||||
conversationId: createResponse.body.conversation.id,
|
||||
|
@ -222,10 +194,8 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
|
||||
it('returns the created conversation when listing', async () => {
|
||||
const response = await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
.slsEditor({
|
||||
endpoint: 'POST /internal/observability_ai_assistant/conversations',
|
||||
roleAuthc,
|
||||
internalReqHeader,
|
||||
})
|
||||
.expect(200);
|
||||
// delete user from response to avoid comparing it as it will be different in MKI
|
||||
|
@ -243,10 +213,8 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
|
||||
before(async () => {
|
||||
updateResponse = await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
.slsEditor({
|
||||
endpoint: 'PUT /internal/observability_ai_assistant/conversation/{conversationId}',
|
||||
internalReqHeader,
|
||||
roleAuthc,
|
||||
params: {
|
||||
path: {
|
||||
conversationId: createResponse.body.conversation.id,
|
||||
|
@ -269,10 +237,8 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
|
||||
it('returns the updated conversation after get', async () => {
|
||||
const updateAfterCreateResponse = await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
.slsEditor({
|
||||
endpoint: 'GET /internal/observability_ai_assistant/conversation/{conversationId}',
|
||||
internalReqHeader,
|
||||
roleAuthc,
|
||||
params: {
|
||||
path: {
|
||||
conversationId: createResponse.body.conversation.id,
|
||||
|
|
|
@ -14,7 +14,6 @@ import {
|
|||
StreamingChatResponseEventType,
|
||||
} from '@kbn/observability-ai-assistant-plugin/common/conversation_complete';
|
||||
import { ObservabilityAIAssistantApiClient } from '../../common/observability_ai_assistant_api_client';
|
||||
import type { InternalRequestHeader, RoleCredentials } from '../../../../../../shared/services';
|
||||
|
||||
export function decodeEvents(body: Readable | string) {
|
||||
return String(body)
|
||||
|
@ -56,20 +55,14 @@ export function getConversationUpdatedEvent(body: Readable | string) {
|
|||
|
||||
export async function deleteAllConversations({
|
||||
observabilityAIAssistantAPIClient,
|
||||
internalReqHeader,
|
||||
roleAuthc,
|
||||
log,
|
||||
}: {
|
||||
observabilityAIAssistantAPIClient: ObservabilityAIAssistantApiClient;
|
||||
internalReqHeader: InternalRequestHeader;
|
||||
roleAuthc: RoleCredentials;
|
||||
log: ToolingLog;
|
||||
}) {
|
||||
const findConversationsResponse = await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
.slsEditor({
|
||||
endpoint: 'POST /internal/observability_ai_assistant/conversations',
|
||||
internalReqHeader,
|
||||
roleAuthc,
|
||||
params: {
|
||||
body: {
|
||||
query: '',
|
||||
|
@ -87,10 +80,8 @@ export async function deleteAllConversations({
|
|||
conversations.map(async (conversation) => {
|
||||
try {
|
||||
await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
.slsEditor({
|
||||
endpoint: 'DELETE /internal/observability_ai_assistant/conversation/{conversationId}',
|
||||
internalReqHeader,
|
||||
roleAuthc,
|
||||
params: {
|
||||
path: {
|
||||
conversationId: conversation.conversation.id,
|
||||
|
|
|
@ -13,59 +13,51 @@ import {
|
|||
deleteKnowledgeBaseModel,
|
||||
} from '@kbn/test-suites-xpack/observability_ai_assistant_api_integration/tests/knowledge_base/helpers';
|
||||
import { FtrProviderContext } from '../../common/ftr_provider_context';
|
||||
import type { InternalRequestHeader, RoleCredentials } from '../../../../../../shared/services';
|
||||
|
||||
export default function ApiTest({ getService }: FtrProviderContext) {
|
||||
const ml = getService('ml');
|
||||
const es = getService('es');
|
||||
const svlUserManager = getService('svlUserManager');
|
||||
const svlCommonApi = getService('svlCommonApi');
|
||||
|
||||
const observabilityAIAssistantAPIClient = getService('observabilityAIAssistantAPIClient');
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/192886
|
||||
describe.skip('Knowledge base', function () {
|
||||
this.tags(['skipMKI']);
|
||||
let roleAuthc: RoleCredentials;
|
||||
let internalReqHeader: InternalRequestHeader;
|
||||
|
||||
before(async () => {
|
||||
roleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('editor');
|
||||
internalReqHeader = svlCommonApi.getInternalRequestHeader();
|
||||
await createKnowledgeBaseModel(ml);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await deleteKnowledgeBaseModel(ml);
|
||||
await deleteInferenceEndpoint({ es });
|
||||
await svlUserManager.invalidateM2mApiKeyWithRoleScope(roleAuthc);
|
||||
});
|
||||
|
||||
it('returns 200 on knowledge base setup', async () => {
|
||||
const res = await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
.slsEditor({
|
||||
endpoint: 'POST /internal/observability_ai_assistant/kb/setup',
|
||||
roleAuthc,
|
||||
internalReqHeader,
|
||||
})
|
||||
.expect(200);
|
||||
expect(res.body).to.eql({});
|
||||
});
|
||||
|
||||
describe('when managing a single entry', () => {
|
||||
const knowledgeBaseEntry = {
|
||||
id: 'my-doc-id-1',
|
||||
title: 'My title',
|
||||
text: 'My content',
|
||||
};
|
||||
|
||||
it('returns 200 on create', async () => {
|
||||
await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
.slsEditor({
|
||||
endpoint: 'POST /internal/observability_ai_assistant/kb/entries/save',
|
||||
params: { body: knowledgeBaseEntry },
|
||||
roleAuthc,
|
||||
internalReqHeader,
|
||||
})
|
||||
.expect(200);
|
||||
const res = await observabilityAIAssistantAPIClient.slsUser({
|
||||
|
||||
const res = await observabilityAIAssistantAPIClient.slsEditor({
|
||||
endpoint: 'GET /internal/observability_ai_assistant/kb/entries',
|
||||
params: {
|
||||
query: {
|
||||
|
@ -74,8 +66,6 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
sortDirection: 'asc',
|
||||
},
|
||||
},
|
||||
roleAuthc,
|
||||
internalReqHeader,
|
||||
});
|
||||
const entry = res.body.entries[0];
|
||||
expect(entry.id).to.equal(knowledgeBaseEntry.id);
|
||||
|
@ -84,7 +74,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
|
||||
it('returns 200 on get entries and entry exists', async () => {
|
||||
const res = await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
.slsEditor({
|
||||
endpoint: 'GET /internal/observability_ai_assistant/kb/entries',
|
||||
params: {
|
||||
query: {
|
||||
|
@ -93,8 +83,6 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
sortDirection: 'asc',
|
||||
},
|
||||
},
|
||||
roleAuthc,
|
||||
internalReqHeader,
|
||||
})
|
||||
.expect(200);
|
||||
const entry = res.body.entries[0];
|
||||
|
@ -105,18 +93,16 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
it('returns 200 on delete', async () => {
|
||||
const entryId = 'my-doc-id-1';
|
||||
await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
.slsEditor({
|
||||
endpoint: 'DELETE /internal/observability_ai_assistant/kb/entries/{entryId}',
|
||||
params: {
|
||||
path: { entryId },
|
||||
},
|
||||
roleAuthc,
|
||||
internalReqHeader,
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
const res = await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
.slsEditor({
|
||||
endpoint: 'GET /internal/observability_ai_assistant/kb/entries',
|
||||
params: {
|
||||
query: {
|
||||
|
@ -125,8 +111,6 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
sortDirection: 'asc',
|
||||
},
|
||||
},
|
||||
roleAuthc,
|
||||
internalReqHeader,
|
||||
})
|
||||
.expect(200);
|
||||
expect(res.body.entries.filter((entry) => entry.id.startsWith('my-doc-id')).length).to.eql(
|
||||
|
@ -137,24 +121,25 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
it('returns 500 on delete not found', async () => {
|
||||
const entryId = 'my-doc-id-1';
|
||||
await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
.slsEditor({
|
||||
endpoint: 'DELETE /internal/observability_ai_assistant/kb/entries/{entryId}',
|
||||
params: {
|
||||
path: { entryId },
|
||||
},
|
||||
roleAuthc,
|
||||
internalReqHeader,
|
||||
})
|
||||
.expect(500);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when managing multiple entries', () => {
|
||||
before(async () => {
|
||||
await clearKnowledgeBase(es);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await clearKnowledgeBase(es);
|
||||
});
|
||||
|
||||
const knowledgeBaseEntries = [
|
||||
{
|
||||
id: 'my_doc_a',
|
||||
|
@ -172,18 +157,17 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
text: 'My content c',
|
||||
},
|
||||
];
|
||||
|
||||
it('returns 200 on create', async () => {
|
||||
await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
.slsEditor({
|
||||
endpoint: 'POST /internal/observability_ai_assistant/kb/entries/import',
|
||||
params: { body: { entries: knowledgeBaseEntries } },
|
||||
roleAuthc,
|
||||
internalReqHeader,
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
const res = await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
.slsEditor({
|
||||
endpoint: 'GET /internal/observability_ai_assistant/kb/entries',
|
||||
params: {
|
||||
query: {
|
||||
|
@ -192,8 +176,6 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
sortDirection: 'asc',
|
||||
},
|
||||
},
|
||||
roleAuthc,
|
||||
internalReqHeader,
|
||||
})
|
||||
.expect(200);
|
||||
expect(res.body.entries.filter((entry) => entry.id.startsWith('my_doc')).length).to.eql(3);
|
||||
|
@ -201,16 +183,14 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
|
||||
it('allows sorting', async () => {
|
||||
await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
.slsEditor({
|
||||
endpoint: 'POST /internal/observability_ai_assistant/kb/entries/import',
|
||||
params: { body: { entries: knowledgeBaseEntries } },
|
||||
roleAuthc,
|
||||
internalReqHeader,
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
const res = await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
.slsEditor({
|
||||
endpoint: 'GET /internal/observability_ai_assistant/kb/entries',
|
||||
params: {
|
||||
query: {
|
||||
|
@ -219,8 +199,6 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
sortDirection: 'desc',
|
||||
},
|
||||
},
|
||||
roleAuthc,
|
||||
internalReqHeader,
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
|
@ -231,7 +209,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
|
||||
// asc
|
||||
const resAsc = await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
.slsEditor({
|
||||
endpoint: 'GET /internal/observability_ai_assistant/kb/entries',
|
||||
params: {
|
||||
query: {
|
||||
|
@ -240,8 +218,6 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
sortDirection: 'asc',
|
||||
},
|
||||
},
|
||||
roleAuthc,
|
||||
internalReqHeader,
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
|
@ -250,18 +226,17 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
expect(entriesAsc[1].id).to.eql('my_doc_b');
|
||||
expect(entriesAsc[2].id).to.eql('my_doc_c');
|
||||
});
|
||||
|
||||
it('allows searching', async () => {
|
||||
await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
.slsEditor({
|
||||
endpoint: 'POST /internal/observability_ai_assistant/kb/entries/import',
|
||||
params: { body: { entries: knowledgeBaseEntries } },
|
||||
roleAuthc,
|
||||
internalReqHeader,
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
const res = await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
.slsEditor({
|
||||
endpoint: 'GET /internal/observability_ai_assistant/kb/entries',
|
||||
params: {
|
||||
query: {
|
||||
|
@ -270,8 +245,6 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
sortDirection: 'asc',
|
||||
},
|
||||
},
|
||||
roleAuthc,
|
||||
internalReqHeader,
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
|
|
|
@ -14,44 +14,30 @@ import {
|
|||
} from '@kbn/test-suites-xpack/observability_ai_assistant_api_integration/tests/knowledge_base/helpers';
|
||||
|
||||
import { FtrProviderContext } from '../../common/ftr_provider_context';
|
||||
import type { InternalRequestHeader, RoleCredentials } from '../../../../../../shared/services';
|
||||
|
||||
export default function ApiTest({ getService }: FtrProviderContext) {
|
||||
const ml = getService('ml');
|
||||
const es = getService('es');
|
||||
const svlUserManager = getService('svlUserManager');
|
||||
const svlCommonApi = getService('svlCommonApi');
|
||||
const observabilityAIAssistantAPIClient = getService('observabilityAIAssistantAPIClient');
|
||||
|
||||
describe('/internal/observability_ai_assistant/kb/setup', function () {
|
||||
this.tags(['skipMKI']);
|
||||
let roleAuthc: RoleCredentials;
|
||||
let internalReqHeader: InternalRequestHeader;
|
||||
|
||||
before(async () => {
|
||||
await deleteKnowledgeBaseModel(ml).catch(() => {});
|
||||
await deleteInferenceEndpoint({ es }).catch(() => {});
|
||||
|
||||
roleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('admin');
|
||||
internalReqHeader = svlCommonApi.getInternalRequestHeader();
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await svlUserManager.invalidateM2mApiKeyWithRoleScope(roleAuthc);
|
||||
});
|
||||
|
||||
it('returns empty object when successful', async () => {
|
||||
await createKnowledgeBaseModel(ml);
|
||||
const res = await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
.slsAdmin({
|
||||
endpoint: 'POST /internal/observability_ai_assistant/kb/setup',
|
||||
params: {
|
||||
query: {
|
||||
model_id: TINY_ELSER.id,
|
||||
},
|
||||
},
|
||||
roleAuthc,
|
||||
internalReqHeader,
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
|
@ -64,15 +50,13 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
|
||||
it('returns bad request if model cannot be installed', async () => {
|
||||
const res = await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
.slsAdmin({
|
||||
endpoint: 'POST /internal/observability_ai_assistant/kb/setup',
|
||||
params: {
|
||||
query: {
|
||||
model_id: TINY_ELSER.id,
|
||||
},
|
||||
},
|
||||
roleAuthc,
|
||||
internalReqHeader,
|
||||
})
|
||||
.expect(500);
|
||||
|
||||
|
|
|
@ -14,34 +14,25 @@ import {
|
|||
} from '@kbn/test-suites-xpack/observability_ai_assistant_api_integration/tests/knowledge_base/helpers';
|
||||
import { AI_ASSISTANT_KB_INFERENCE_ID } from '@kbn/observability-ai-assistant-plugin/server/service/inference_endpoint';
|
||||
import { FtrProviderContext } from '../../common/ftr_provider_context';
|
||||
import type { InternalRequestHeader, RoleCredentials } from '../../../../../../shared/services';
|
||||
|
||||
export default function ApiTest({ getService }: FtrProviderContext) {
|
||||
const ml = getService('ml');
|
||||
const es = getService('es');
|
||||
const svlUserManager = getService('svlUserManager');
|
||||
const svlCommonApi = getService('svlCommonApi');
|
||||
const observabilityAIAssistantAPIClient = getService('observabilityAIAssistantAPIClient');
|
||||
|
||||
describe('/internal/observability_ai_assistant/kb/status', function () {
|
||||
this.tags(['skipMKI']);
|
||||
let roleAuthc: RoleCredentials;
|
||||
let internalReqHeader: InternalRequestHeader;
|
||||
|
||||
before(async () => {
|
||||
roleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('admin');
|
||||
internalReqHeader = svlCommonApi.getInternalRequestHeader();
|
||||
await createKnowledgeBaseModel(ml);
|
||||
await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
.slsAdmin({
|
||||
endpoint: 'POST /internal/observability_ai_assistant/kb/setup',
|
||||
params: {
|
||||
query: {
|
||||
model_id: TINY_ELSER.id,
|
||||
},
|
||||
},
|
||||
roleAuthc,
|
||||
internalReqHeader,
|
||||
})
|
||||
.expect(200);
|
||||
});
|
||||
|
@ -49,15 +40,12 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
after(async () => {
|
||||
await deleteKnowledgeBaseModel(ml);
|
||||
await deleteInferenceEndpoint({ es, name: AI_ASSISTANT_KB_INFERENCE_ID }).catch((err) => {});
|
||||
await svlUserManager.invalidateM2mApiKeyWithRoleScope(roleAuthc);
|
||||
});
|
||||
|
||||
it('returns correct status after knowledge base is setup', async () => {
|
||||
const res = await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
.slsEditor({
|
||||
endpoint: 'GET /internal/observability_ai_assistant/kb/status',
|
||||
roleAuthc,
|
||||
internalReqHeader,
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
|
@ -70,10 +58,8 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
await deleteInferenceEndpoint({ es, name: AI_ASSISTANT_KB_INFERENCE_ID });
|
||||
|
||||
const res = await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
.slsEditor({
|
||||
endpoint: 'GET /internal/observability_ai_assistant/kb/status',
|
||||
roleAuthc,
|
||||
internalReqHeader,
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
|
|
|
@ -34,26 +34,19 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
const svlUserManager = getService('svlUserManager');
|
||||
const svlCommonApi = getService('svlCommonApi');
|
||||
|
||||
// TODO: https://github.com/elastic/kibana/issues/192711 cannot create custom users in serverless
|
||||
// trying using built in users by using cookie auth
|
||||
// TODO: https://github.com/elastic/kibana/issues/192757
|
||||
describe.skip('Knowledge base user instructions', function () {
|
||||
this.tags(['skipMKI']);
|
||||
let editorRoleAuthc: RoleCredentials;
|
||||
let johnRoleAuthc: RoleCredentials;
|
||||
let internalReqHeader: InternalRequestHeader;
|
||||
|
||||
before(async () => {
|
||||
// Create API keys for 'editor' role, simulating different users
|
||||
johnRoleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('admin');
|
||||
editorRoleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('editor');
|
||||
internalReqHeader = svlCommonApi.getInternalRequestHeader();
|
||||
await createKnowledgeBaseModel(ml);
|
||||
|
||||
await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
.slsEditor({
|
||||
endpoint: 'POST /internal/observability_ai_assistant/kb/setup',
|
||||
roleAuthc: editorRoleAuthc,
|
||||
internalReqHeader,
|
||||
})
|
||||
.expect(200);
|
||||
});
|
||||
|
@ -63,7 +56,6 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
await deleteInferenceEndpoint({ es });
|
||||
await clearKnowledgeBase(es);
|
||||
await clearConversations(es);
|
||||
await svlUserManager.invalidateM2mApiKeyWithRoleScope(johnRoleAuthc);
|
||||
await svlUserManager.invalidateM2mApiKeyWithRoleScope(editorRoleAuthc);
|
||||
});
|
||||
|
||||
|
@ -72,37 +64,34 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
await clearKnowledgeBase(es);
|
||||
|
||||
const promises = [
|
||||
{ roleAuthc: editorRoleAuthc, username: 'editor', isPublic: true },
|
||||
{ roleAuthc: editorRoleAuthc, username: 'editor', isPublic: false },
|
||||
{ roleAuthc: johnRoleAuthc, username: 'john', isPublic: true },
|
||||
{ roleAuthc: johnRoleAuthc, username: 'john', isPublic: false },
|
||||
].map(async ({ roleAuthc, username, isPublic }) => {
|
||||
{ username: 'editor', isPublic: true },
|
||||
{ username: 'editor', isPublic: false },
|
||||
{ username: 'john', isPublic: true },
|
||||
{ username: 'john', isPublic: false },
|
||||
].map(async ({ username, isPublic }) => {
|
||||
const visibility = isPublic ? 'Public' : 'Private';
|
||||
await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
endpoint: 'PUT /internal/observability_ai_assistant/kb/user_instructions',
|
||||
params: {
|
||||
body: {
|
||||
id: `${visibility.toLowerCase()}-doc-from-${username}`,
|
||||
text: `${visibility} user instruction from "${username}"`,
|
||||
public: isPublic,
|
||||
},
|
||||
const user = username === 'editor' ? 'slsEditor' : 'slsAdmin';
|
||||
|
||||
await observabilityAIAssistantAPIClient[user]({
|
||||
endpoint: 'PUT /internal/observability_ai_assistant/kb/user_instructions',
|
||||
params: {
|
||||
body: {
|
||||
id: `${visibility.toLowerCase()}-doc-from-${username}`,
|
||||
text: `${visibility} user instruction from "${username}"`,
|
||||
public: isPublic,
|
||||
},
|
||||
roleAuthc,
|
||||
internalReqHeader,
|
||||
})
|
||||
.expect(200);
|
||||
},
|
||||
}).expect(200);
|
||||
});
|
||||
|
||||
await Promise.all(promises);
|
||||
});
|
||||
|
||||
it('"editor" can retrieve their own private instructions and the public instruction', async () => {
|
||||
const res = await observabilityAIAssistantAPIClient.slsUser({
|
||||
const res = await observabilityAIAssistantAPIClient.slsEditor({
|
||||
endpoint: 'GET /internal/observability_ai_assistant/kb/user_instructions',
|
||||
roleAuthc: editorRoleAuthc,
|
||||
internalReqHeader,
|
||||
});
|
||||
|
||||
const instructions = res.body.userInstructions;
|
||||
|
||||
const sortByDocId = (data: any) => sortBy(data, 'doc_id');
|
||||
|
@ -128,11 +117,10 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
});
|
||||
|
||||
it('"john" can retrieve their own private instructions and the public instruction', async () => {
|
||||
const res = await observabilityAIAssistantAPIClient.slsUser({
|
||||
const res = await observabilityAIAssistantAPIClient.slsAdmin({
|
||||
endpoint: 'GET /internal/observability_ai_assistant/kb/user_instructions',
|
||||
roleAuthc: johnRoleAuthc,
|
||||
internalReqHeader,
|
||||
});
|
||||
|
||||
const instructions = res.body.userInstructions;
|
||||
|
||||
const sortByDocId = (data: any) => sortBy(data, 'doc_id');
|
||||
|
@ -163,7 +151,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
await clearKnowledgeBase(es);
|
||||
|
||||
await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
.slsEditor({
|
||||
endpoint: 'PUT /internal/observability_ai_assistant/kb/user_instructions',
|
||||
params: {
|
||||
body: {
|
||||
|
@ -172,13 +160,11 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
public: true,
|
||||
},
|
||||
},
|
||||
roleAuthc: editorRoleAuthc,
|
||||
internalReqHeader,
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
.slsEditor({
|
||||
endpoint: 'PUT /internal/observability_ai_assistant/kb/user_instructions',
|
||||
params: {
|
||||
body: {
|
||||
|
@ -187,18 +173,15 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
public: false,
|
||||
},
|
||||
},
|
||||
roleAuthc: editorRoleAuthc,
|
||||
internalReqHeader,
|
||||
})
|
||||
.expect(200);
|
||||
});
|
||||
|
||||
it('updates the user instruction', async () => {
|
||||
const res = await observabilityAIAssistantAPIClient.slsUser({
|
||||
const res = await observabilityAIAssistantAPIClient.slsEditor({
|
||||
endpoint: 'GET /internal/observability_ai_assistant/kb/user_instructions',
|
||||
roleAuthc: editorRoleAuthc,
|
||||
internalReqHeader,
|
||||
});
|
||||
|
||||
const instructions = res.body.userInstructions;
|
||||
|
||||
expect(instructions).to.eql([
|
||||
|
@ -218,10 +201,12 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
const userInstructionText =
|
||||
'Be polite and use language that is easy to understand. Never disagree with the user.';
|
||||
|
||||
async function getConversationForUser(roleAuthc: RoleCredentials) {
|
||||
async function getConversationForUser(username: string) {
|
||||
const user = username === 'editor' ? 'slsEditor' : 'slsAdmin';
|
||||
|
||||
// the user instruction is always created by "editor" user
|
||||
await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
.slsEditor({
|
||||
endpoint: 'PUT /internal/observability_ai_assistant/kb/user_instructions',
|
||||
params: {
|
||||
body: {
|
||||
|
@ -230,8 +215,6 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
public: false,
|
||||
},
|
||||
},
|
||||
roleAuthc: editorRoleAuthc,
|
||||
internalReqHeader,
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
|
@ -259,36 +242,30 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
},
|
||||
];
|
||||
|
||||
const createResponse = await observabilityAIAssistantAPIClient
|
||||
.slsUser({
|
||||
endpoint: 'POST /internal/observability_ai_assistant/chat/complete',
|
||||
params: {
|
||||
body: {
|
||||
messages,
|
||||
connectorId,
|
||||
persist: true,
|
||||
screenContexts: [],
|
||||
scopes: ['observability'],
|
||||
},
|
||||
const createResponse = await observabilityAIAssistantAPIClient[user]({
|
||||
endpoint: 'POST /internal/observability_ai_assistant/chat/complete',
|
||||
params: {
|
||||
body: {
|
||||
messages,
|
||||
connectorId,
|
||||
persist: true,
|
||||
screenContexts: [],
|
||||
scopes: ['observability'],
|
||||
},
|
||||
roleAuthc,
|
||||
internalReqHeader,
|
||||
})
|
||||
.expect(200);
|
||||
},
|
||||
}).expect(200);
|
||||
|
||||
await proxy.waitForAllInterceptorsSettled();
|
||||
const conversationCreatedEvent = getConversationCreatedEvent(createResponse.body);
|
||||
const conversationId = conversationCreatedEvent.conversation.id;
|
||||
|
||||
const res = await observabilityAIAssistantAPIClient.slsUser({
|
||||
const res = await observabilityAIAssistantAPIClient[user]({
|
||||
endpoint: 'GET /internal/observability_ai_assistant/conversation/{conversationId}',
|
||||
params: {
|
||||
path: {
|
||||
conversationId,
|
||||
},
|
||||
},
|
||||
roleAuthc,
|
||||
internalReqHeader,
|
||||
});
|
||||
|
||||
// wait for all interceptors to be settled
|
||||
|
@ -321,7 +298,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
});
|
||||
|
||||
it('adds the instruction to the system prompt', async () => {
|
||||
const conversation = await getConversationForUser(editorRoleAuthc);
|
||||
const conversation = await getConversationForUser('editor');
|
||||
const systemMessage = conversation.messages.find(
|
||||
(message) => message.message.role === MessageRole.System
|
||||
)!;
|
||||
|
@ -329,7 +306,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
});
|
||||
|
||||
it('does not add the instruction to the context', async () => {
|
||||
const conversation = await getConversationForUser(editorRoleAuthc);
|
||||
const conversation = await getConversationForUser('editor');
|
||||
const contextMessage = conversation.messages.find(
|
||||
(message) => message.message.name === CONTEXT_FUNCTION_NAME
|
||||
);
|
||||
|
@ -343,7 +320,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
});
|
||||
|
||||
it('does not add the instruction conversation for other users', async () => {
|
||||
const conversation = await getConversationForUser(johnRoleAuthc);
|
||||
const conversation = await getConversationForUser('john');
|
||||
const systemMessage = conversation.messages.find(
|
||||
(message) => message.message.role === MessageRole.System
|
||||
)!;
|
||||
|
|
|
@ -48,6 +48,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
},
|
||||
},
|
||||
];
|
||||
|
||||
describe('/api/observability_ai_assistant/chat/complete', function () {
|
||||
// TODO: https://github.com/elastic/kibana/issues/192751
|
||||
this.tags(['skipMKI']);
|
||||
|
@ -108,6 +109,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
await titleSimulator.complete();
|
||||
|
||||
await conversationSimulator.status(200);
|
||||
|
||||
if (conversationSimulatorCallback) {
|
||||
await conversationSimulatorCallback(conversationSimulator);
|
||||
}
|
||||
|
@ -158,8 +160,6 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
after(async () => {
|
||||
await deleteAllConversations({
|
||||
observabilityAIAssistantAPIClient,
|
||||
internalReqHeader,
|
||||
roleAuthc,
|
||||
log,
|
||||
});
|
||||
await deleteActionConnector({ supertest, connectorId, log, roleAuthc, internalReqHeader });
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue