diff --git a/x-pack/plugins/security_solution/scripts/run_cypress/parallel_serverless.ts b/x-pack/plugins/security_solution/scripts/run_cypress/parallel_serverless.ts index 8e680e8ebc451..0b426cf1e8c20 100644 --- a/x-pack/plugins/security_solution/scripts/run_cypress/parallel_serverless.ts +++ b/x-pack/plugins/security_solution/scripts/run_cypress/parallel_serverless.ts @@ -93,7 +93,11 @@ export function proxyHealthcheck(proxyUrl: string): Promise { } // Wait until elasticsearch status goes green -export function waitForEsStatusGreen(esUrl: string, auth: string, runnerId: string): Promise { +export function waitForEsStatusGreen( + esUrl: string, + auth: string, + projectId: string +): Promise { const fetchHealthStatusAttempt = async (attemptNum: number) => { log.info(`Retry number ${attemptNum} to check if Elasticsearch is green.`); @@ -105,13 +109,13 @@ export function waitForEsStatusGreen(esUrl: string, auth: string, runnerId: stri }) .catch(catchAxiosErrorFormatAndThrow); - log.info(`${runnerId}: Elasticsearch is ready with status ${response.data.status}.`); + log.info(`${projectId}: Elasticsearch is ready with status ${response.data.status}.`); }; const retryOptions = { onFailedAttempt: (error: Error | AxiosError) => { if (error instanceof AxiosError && error.code === 'ENOTFOUND') { log.info( - `${runnerId}: The Elasticsearch URL is not yet reachable. A retry will be triggered soon...` + `${projectId}: The Elasticsearch URL is not yet reachable. A retry will be triggered soon...` ); } }, @@ -127,7 +131,7 @@ export function waitForEsStatusGreen(esUrl: string, auth: string, runnerId: stri export function waitForKibanaAvailable( kbUrl: string, auth: string, - runnerId: string + projectId: string ): Promise { const fetchKibanaStatusAttempt = async (attemptNum: number) => { log.info(`Retry number ${attemptNum} to check if kibana is available.`); @@ -139,19 +143,19 @@ export function waitForKibanaAvailable( }) .catch(catchAxiosErrorFormatAndThrow); if (response.data.status.overall.level !== 'available') { - throw new Error(`${runnerId}: Kibana is not available. A retry will be triggered soon...`); + throw new Error(`${projectId}: Kibana is not available. A retry will be triggered soon...`); } else { - log.info(`${runnerId}: Kibana status overall is ${response.data.status.overall.level}.`); + log.info(`${projectId}: Kibana status overall is ${response.data.status.overall.level}.`); } }; const retryOptions = { onFailedAttempt: (error: Error | AxiosError) => { if (error instanceof AxiosError && error.code === 'ENOTFOUND') { log.info( - `${runnerId}: The Kibana URL is not yet reachable. A retry will be triggered soon...` + `${projectId}: The Kibana URL is not yet reachable. A retry will be triggered soon...` ); } else { - log.info(`${runnerId}: ${error.message}`); + log.info(`${projectId}: ${error.message}`); } }, retries: 50, @@ -162,7 +166,7 @@ export function waitForKibanaAvailable( } // Wait for Elasticsearch to be accessible -export function waitForEsAccess(esUrl: string, auth: string, runnerId: string): Promise { +export function waitForEsAccess(esUrl: string, auth: string, projectId: string): Promise { const fetchEsAccessAttempt = async (attemptNum: number) => { log.info(`Retry number ${attemptNum} to check if can be accessed.`); @@ -178,7 +182,7 @@ export function waitForEsAccess(esUrl: string, auth: string, runnerId: string): onFailedAttempt: (error: Error | AxiosError) => { if (error instanceof AxiosError && error.code === 'ENOTFOUND') { log.info( - `${runnerId}: The elasticsearch url is not yet reachable. A retry will be triggered soon...` + `${projectId}: The elasticsearch url is not yet reachable. A retry will be triggered soon...` ); } }, @@ -447,7 +451,7 @@ ${JSON.stringify(cypressConfigFile, null, 2)} : (parseTestFileConfig(filePath).productTypes as ProductType[]); log.info(`Running spec file: ${filePath}`); - log.info(`${id}: Creating project ${PROJECT_NAME}...`); + log.info(`Creating project ${PROJECT_NAME}...`); // Creating project for the test to run const project = await cloudHandler.createSecurityProject( PROJECT_NAME, @@ -461,6 +465,21 @@ ${JSON.stringify(cypressConfigFile, null, 2)} return process.exit(1); } + log.info(` + ----------------------------------------------- + Project created with details: + ----------------------------------------------- + ID: ${project.id} + Name: ${project.name} + Region: ${project.region} + Elasticsearch URL: ${project.es_url} + Kibana URL: ${project.kb_url} + Product: ${project.product} + Organization ID: ${project.proxy_org_id} + Organization Name: ${project.proxy_org_name} + ----------------------------------------------- + `); + context.addCleanupTask(() => { let command: string; if (cloudHandler instanceof CloudHandler) { @@ -470,7 +489,7 @@ ${JSON.stringify(cypressConfigFile, null, 2)} }); // Reset credentials for elastic user - const credentials = await cloudHandler.resetCredentials(project.id, id); + const credentials = await cloudHandler.resetCredentials(project.id); if (!credentials) { log.error('Credentials could not be reset.'); @@ -485,13 +504,13 @@ ${JSON.stringify(cypressConfigFile, null, 2)} const auth = btoa(`${credentials.username}:${credentials.password}`); // Wait for elasticsearch status to go green. - await waitForEsStatusGreen(project.es_url, auth, id); + await waitForEsStatusGreen(project.es_url, auth, project.id); // Wait until Kibana is available - await waitForKibanaAvailable(project.kb_url, auth, id); + await waitForKibanaAvailable(project.kb_url, auth, project.id); // Wait for Elasticsearch to be accessible - await waitForEsAccess(project.es_url, auth, id); + await waitForEsAccess(project.es_url, auth, project.id); // Wait until application is ready await waitForKibanaLogin(project.kb_url, credentials); @@ -499,7 +518,6 @@ ${JSON.stringify(cypressConfigFile, null, 2)} // Check if proxy service is used to define which org executes the tests. const proxyOrg = cloudHandler instanceof ProxyHandler ? project.proxy_org_name : undefined; - log.info(`Proxy Organization used id : ${proxyOrg}`); // Normalized the set of available env vars in cypress const cyCustomEnv = { @@ -576,13 +594,14 @@ ${JSON.stringify(cypressConfigFile, null, 2)} failedSpecFilePaths.push(filePath); } // Delete serverless project - log.info(`${id} : Deleting project ${PROJECT_NAME}...`); + log.info(`Deleting project ${PROJECT_NAME} and ID ${project.id} ...`); await cloudHandler.deleteSecurityProject(project.id, PROJECT_NAME); } catch (error) { // False positive // eslint-disable-next-line require-atomic-updates result = error; failedSpecFilePaths.push(filePath); + log.error(`Cypress runner failed: ${error}`); } } return result; diff --git a/x-pack/plugins/security_solution/scripts/run_cypress/project_handler/cloud_project_handler.ts b/x-pack/plugins/security_solution/scripts/run_cypress/project_handler/cloud_project_handler.ts index 5ae476c17580e..2d41b9605b275 100644 --- a/x-pack/plugins/security_solution/scripts/run_cypress/project_handler/cloud_project_handler.ts +++ b/x-pack/plugins/security_solution/scripts/run_cypress/project_handler/cloud_project_handler.ts @@ -105,8 +105,8 @@ export class CloudHandler extends ProjectHandler { } // Method to reset the credentials for the created project. - resetCredentials(projectId: string, runnerId: string): Promise { - this.log.info(`${runnerId} : Reseting credentials`); + resetCredentials(projectId: string): Promise { + this.log.info(`${projectId} : Reseting credentials`); const fetchResetCredentialsStatusAttempt = async (attemptNum: number) => { const response = await axios.post( @@ -118,7 +118,7 @@ export class CloudHandler extends ProjectHandler { }, } ); - this.log.info('Credentials have ben reset'); + this.log.info('Credentials have been reset'); return { password: response.data.password, username: response.data.username, diff --git a/x-pack/plugins/security_solution/scripts/run_cypress/project_handler/project_handler.ts b/x-pack/plugins/security_solution/scripts/run_cypress/project_handler/project_handler.ts index f84bc6d9961ce..6560a9a5cbdfa 100644 --- a/x-pack/plugins/security_solution/scripts/run_cypress/project_handler/project_handler.ts +++ b/x-pack/plugins/security_solution/scripts/run_cypress/project_handler/project_handler.ts @@ -75,7 +75,7 @@ export class ProjectHandler { throw new Error(this.DEFAULT_ERROR_MSG); } - resetCredentials(projectId: string, runnerId: string): Promise { + resetCredentials(projectId: string): Promise { throw new Error(this.DEFAULT_ERROR_MSG); } diff --git a/x-pack/plugins/security_solution/scripts/run_cypress/project_handler/proxy_project_handler.ts b/x-pack/plugins/security_solution/scripts/run_cypress/project_handler/proxy_project_handler.ts index dfc97e9a422d8..ec7794389233f 100644 --- a/x-pack/plugins/security_solution/scripts/run_cypress/project_handler/proxy_project_handler.ts +++ b/x-pack/plugins/security_solution/scripts/run_cypress/project_handler/proxy_project_handler.ts @@ -104,8 +104,8 @@ export class ProxyHandler extends ProjectHandler { } // Method to reset the credentials for the created project. - resetCredentials(projectId: string, runnerId: string): Promise { - this.log.info(`${runnerId} : Reseting credentials`); + resetCredentials(projectId: string): Promise { + this.log.info(`${projectId} : Reseting credentials`); const fetchResetCredentialsStatusAttempt = async (attemptNum: number) => { const response = await axios.post( @@ -117,7 +117,7 @@ export class ProxyHandler extends ProjectHandler { }, } ); - this.log.info('Credentials have ben reset'); + this.log.info('Credentials have been reset'); return { password: response.data.password, username: response.data.username, diff --git a/x-pack/test/security_solution_api_integration/scripts/mki_api_ftr_execution.ts b/x-pack/test/security_solution_api_integration/scripts/mki_api_ftr_execution.ts index 7241d28f9c29b..f7a187715bd10 100644 --- a/x-pack/test/security_solution_api_integration/scripts/mki_api_ftr_execution.ts +++ b/x-pack/test/security_solution_api_integration/scripts/mki_api_ftr_execution.ts @@ -117,19 +117,36 @@ export const cli = () => { const productTypes = await parseProductTypes(log); // Creating project for the test to run + log.info(`${id}: Creating project ${PROJECT_NAME}...`); const project = await cloudHandler.createSecurityProject(PROJECT_NAME, productTypes); - // Check if proxy service is used to define which org executes the tests. - const proxyOrg = cloudHandler instanceof ProxyHandler ? project?.proxy_org_name : undefined; - log.info(`Proxy Organization used id : ${proxyOrg}`); if (!project) { log.error('Failed to create project.'); return process.exit(1); } + + log.info(` + ----------------------------------------------- + Project created with details: + ----------------------------------------------- + ID: ${project.id} + Name: ${project.name} + Region: ${project.region} + Elasticsearch URL: ${project.es_url} + Kibana URL: ${project.kb_url} + Product: ${project.product} + Organization ID: ${project.proxy_org_id} + Organization Name: ${project.proxy_org_name} + ----------------------------------------------- + `); + + // Check if proxy service is used to define which org executes the tests. + const proxyOrg = cloudHandler instanceof ProxyHandler ? project?.proxy_org_name : undefined; + let statusCode: number = 0; try { // Reset credentials for elastic user - const credentials = await cloudHandler.resetCredentials(project.id, id); + const credentials = await cloudHandler.resetCredentials(project.id); if (!credentials) { log.error('Credentials could not be reset.'); @@ -144,13 +161,13 @@ export const cli = () => { const auth = btoa(`${credentials.username}:${credentials.password}`); // Wait for elasticsearch status to go green. - await waitForEsStatusGreen(project.es_url, auth, id); + await waitForEsStatusGreen(project.es_url, auth, project.id); // Wait until Kibana is available - await waitForKibanaAvailable(project.kb_url, auth, id); + await waitForKibanaAvailable(project.kb_url, auth, project.id); // Wait for Elasticsearch to be accessible - await waitForEsAccess(project.es_url, auth, id); + await waitForEsAccess(project.es_url, auth, project.id); const FORMATTED_ES_URL = project.es_url.replace('https://', ''); const FORMATTED_KB_URL = project.kb_url.replace('https://', ''); @@ -175,7 +192,7 @@ export const cli = () => { statusCode = 1; } finally { // Delete serverless project - log.info(`${id} : Deleting project ${PROJECT_NAME}...`); + log.info(`Deleting project ${PROJECT_NAME} and ID ${project.id} ...`); await cloudHandler.deleteSecurityProject(project.id, PROJECT_NAME); } process.exit(statusCode); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/explore/network/hover_actions.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/explore/network/hover_actions.cy.ts index 7d6ab6abdb8be..db00bc4d45bbb 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/explore/network/hover_actions.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/explore/network/hover_actions.cy.ts @@ -48,6 +48,14 @@ describe('Hover actions', { tags: ['@ess', '@serverless'] }, () => { mouseoverOnToOverflowItem(); }); + it('Copy value', () => { + cy.document().then((doc) => cy.spy(doc, 'execCommand').as('execCommand')); + + clickOnCopyValue(); + + cy.get('@execCommand').should('have.been.calledOnceWith', 'copy'); + }); + it('Adds global filter - filter in', () => { clickOnFilterIn(); @@ -75,12 +83,4 @@ describe('Hover actions', { tags: ['@ess', '@serverless'] }, () => { clickOnShowTopN(); cy.get(TOP_N_CONTAINER).should('exist').should('contain.text', 'Top destination.domain'); }); - - it('Copy value', () => { - cy.document().then((doc) => cy.spy(doc, 'execCommand').as('execCommand')); - - clickOnCopyValue(); - - cy.get('@execCommand').should('have.been.calledOnceWith', 'copy'); - }); });