[9.0] [Cloud Security] fix cnvm and cspm agentless flaky tests (#216793) (#216880)

# Backport

This will backport the following commits from `main` to `9.0`:
- [[Cloud Security] fix cnvm and cspm agentless flaky tests
(#216793)](https://github.com/elastic/kibana/pull/216793)

<!--- Backport version: 9.6.6 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sorenlouv/backport)

<!--BACKPORT [{"author":{"name":"Alex
Prozorov","email":"alex.prozorov@elastic.co"},"sourceCommit":{"committedDate":"2025-04-02T15:30:27Z","message":"[Cloud
Security] fix cnvm and cspm agentless flaky tests (#216793)\n\n##
Summary\n\nThis PR fixes the flakiness of in the following issues
-\n[190967](https://github.com/elastic/kibana/issues/190967)
and\n[209529](https://github.com/elastic/kibana/issues/209529).\nthe
observed issue was that the loader in the page headers
sometimes\nremains on the screen even though the modal is already
visible. Seems\nlike its stuck sometimes. Therefore changed the check to
see if the\n'Launch Cloud formation' button exists instead of relying on
the loader\nindicator.\n\n\n### Checklist\n\nReviewers should verify
this PR satisfies this list as well.\n- [x] [Flaky
Test\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1)
was\nused on any tests changed\n- [x] The PR description includes the
appropriate Release Notes section,\nand the correct `release_note:*`
label is applied per
the\n[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)","sha":"8a7860cf6130e389d5efe8b3f49087dd9bc321fb","branchLabelMapping":{"^v9.1.0$":"main","^v8.19.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","Team:Cloud
Security","backport:prev-minor","backport:prev-major","v9.1.0"],"title":"[Cloud
Security] fix cnvm and cspm agentless flaky
tests","number":216793,"url":"https://github.com/elastic/kibana/pull/216793","mergeCommit":{"message":"[Cloud
Security] fix cnvm and cspm agentless flaky tests (#216793)\n\n##
Summary\n\nThis PR fixes the flakiness of in the following issues
-\n[190967](https://github.com/elastic/kibana/issues/190967)
and\n[209529](https://github.com/elastic/kibana/issues/209529).\nthe
observed issue was that the loader in the page headers
sometimes\nremains on the screen even though the modal is already
visible. Seems\nlike its stuck sometimes. Therefore changed the check to
see if the\n'Launch Cloud formation' button exists instead of relying on
the loader\nindicator.\n\n\n### Checklist\n\nReviewers should verify
this PR satisfies this list as well.\n- [x] [Flaky
Test\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1)
was\nused on any tests changed\n- [x] The PR description includes the
appropriate Release Notes section,\nand the correct `release_note:*`
label is applied per
the\n[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)","sha":"8a7860cf6130e389d5efe8b3f49087dd9bc321fb"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v9.1.0","branchLabelMappingKey":"^v9.1.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/216793","number":216793,"mergeCommit":{"message":"[Cloud
Security] fix cnvm and cspm agentless flaky tests (#216793)\n\n##
Summary\n\nThis PR fixes the flakiness of in the following issues
-\n[190967](https://github.com/elastic/kibana/issues/190967)
and\n[209529](https://github.com/elastic/kibana/issues/209529).\nthe
observed issue was that the loader in the page headers
sometimes\nremains on the screen even though the modal is already
visible. Seems\nlike its stuck sometimes. Therefore changed the check to
see if the\n'Launch Cloud formation' button exists instead of relying on
the loader\nindicator.\n\n\n### Checklist\n\nReviewers should verify
this PR satisfies this list as well.\n- [x] [Flaky
Test\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1)
was\nused on any tests changed\n- [x] The PR description includes the
appropriate Release Notes section,\nand the correct `release_note:*`
label is applied per
the\n[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)","sha":"8a7860cf6130e389d5efe8b3f49087dd9bc321fb"}}]}]
BACKPORT-->

Co-authored-by: Alex Prozorov <alex.prozorov@elastic.co>
This commit is contained in:
Kibana Machine 2025-04-02 19:27:49 +02:00 committed by GitHub
parent 6c432a835a
commit 70640db81d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 80 additions and 41 deletions

View file

@ -66,8 +66,10 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
await cisIntegration.clickSaveButton();
await pageObjects.header.waitUntilLoadingHasFinished();
expect(await cisIntegrationAws.showPostInstallCloudFormationModal()).to.be(false);
await retry.tryForTime(agentCreationTimeout, async () => {
await cisIntegration.waitUntilLaunchCloudFormationButtonAppears();
expect(await cisIntegrationAws.showPostInstallCloudFormationModal()).to.be(false);
});
await cisIntegration.navigateToIntegrationCspList();
await pageObjects.header.waitUntilLoadingHasFinished();
@ -106,9 +108,11 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
await cisIntegration.fillInTextField('passwordInput-secret-access-key', 'secret_access_key');
await cisIntegration.clickSaveButton();
await pageObjects.header.waitUntilLoadingHasFinished();
expect(await cisIntegrationAws.showPostInstallCloudFormationModal()).to.be(false);
await retry.tryForTime(agentCreationTimeout, async () => {
await cisIntegration.waitUntilLaunchCloudFormationButtonAppears();
expect(await cisIntegrationAws.showPostInstallCloudFormationModal()).to.be(false);
});
await cisIntegration.navigateToIntegrationCspList();
await pageObjects.header.waitUntilLoadingHasFinished();
@ -138,7 +142,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
// add timeout to give extra time for the modal to show up
await retry.tryForTime(agentCreationTimeout, async () => {
await pageObjects.header.waitUntilLoadingHasFinished();
await cisIntegration.waitUntilLaunchCloudFormationButtonAppears();
const resStatus = await cisIntegrationAws.showPostInstallCloudFormationModal();
expect(resStatus).to.be(true);
});
@ -166,9 +170,11 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
await pageObjects.header.waitUntilLoadingHasFinished();
await cisIntegration.clickSaveButton();
await pageObjects.header.waitUntilLoadingHasFinished();
expect(await cisIntegrationAws.showPostInstallCloudFormationModal()).to.be(true);
await retry.tryForTime(agentCreationTimeout, async () => {
await cisIntegration.waitUntilLaunchCloudFormationButtonAppears();
expect(await cisIntegrationAws.showPostInstallCloudFormationModal()).to.be(true);
});
const agentPolicyName = await cisIntegration.getAgentBasedPolicyValue();

View file

@ -11,6 +11,31 @@ import expect from '@kbn/expect';
import { testSubjectIds } from '../constants/test_subject_ids';
import type { FtrProviderContext } from '../ftr_provider_context';
const TEST_IDS = {
POST_INSTALL_AZURE_ARM_TEMPLATE_MODAL: 'postInstallAzureArmTemplateModal',
EXTERNAL_LINK: 'externalLink',
POST_INSTALL_CLOUD_FORMATION_MODAL: 'postInstallCloudFormationModal',
LAUNCH_CLOUD_FORMATION_AGENTLESS_BUTTON: 'launchCloudFormationAgentlessButton',
POST_INSTALL_GOOGLE_CLOUD_SHELL_MODAL: 'postInstallGoogleCloudShellModal',
DATA_COLLECTION_SETUP_STEP: 'dataCollectionSetupStep',
INTEGRATION_NAME_LINK: 'integrationNameLink',
AGENT_ENROLLMENT_FLYOUT: 'agentEnrollmentFlyout',
AGENTLESS_INTEGRATION_NAME_LINK: 'agentlessIntegrationNameLink',
INTEGRATION_POLICY_TABLE: 'integrationPolicyTable',
EDIT_PACKAGE_POLICY_PAGE: 'editPackagePolicy_page',
CREATE_PACKAGE_POLICY_PAGE: 'createPackagePolicy_page',
CREATE_PACKAGE_POLICY_SAVE_BUTTON: 'createPackagePolicySaveButton',
CONFIRM_CLOUD_FORMATION_MODAL_CONFIRM_BUTTON: 'confirmCloudFormationModalConfirmButton',
SAVE_INTEGRATION: 'saveIntegration',
CONFIRM_MODAL_TITLE_TEXT: 'confirmModalTitleText',
CLOUD_SECURITY_POSTURE_PLI_AUTH_BLOCK: 'cloud-security-posture-integration-pli-auth-block',
ADD_AGENT_BUTTON: 'addAgentButton',
POLICY_UPDATE_SUCCESS_TOAST: 'policyUpdateSuccessToast',
AGENT_POLICY_NAME_LINK: 'agentPolicyNameLink',
AGENTLESS_STATUS_BADGE: 'agentlessStatusBadge',
CREATE_AGENT_POLICY_NAME_FIELD: 'createAgentPolicyNameField',
} as const;
export function AddCisIntegrationFormPageProvider({
getService,
getPageObjects,
@ -24,31 +49,35 @@ export function AddCisIntegrationFormPageProvider({
const cisAzure = {
getPostInstallArmTemplateModal: async () => {
return await testSubjects.find('postInstallAzureArmTemplateModal');
return await testSubjects.find(TEST_IDS.POST_INSTALL_AZURE_ARM_TEMPLATE_MODAL);
},
};
const cisAws = {
getUrlValueInEditPage: async () => {
/* Newly added/edited integration always shows up on top by default as such we can just always click the most top if we want to check for the latest one */
const fieldValue = await (await testSubjects.find('externalLink')).getAttribute('href');
const fieldValue = await (
await testSubjects.find(TEST_IDS.EXTERNAL_LINK)
).getAttribute('href');
return fieldValue;
},
getPostInstallCloudFormationModal: async () => {
return await testSubjects.find('postInstallCloudFormationModal');
return await testSubjects.find(TEST_IDS.POST_INSTALL_CLOUD_FORMATION_MODAL);
},
showPostInstallCloudFormationModal: async () => {
return await testSubjects.exists('postInstallCloudFormationModal');
return await testSubjects.exists(TEST_IDS.POST_INSTALL_CLOUD_FORMATION_MODAL);
},
showLaunchCloudFormationAgentlessButton: async () => {
return await testSubjects.exists('launchCloudFormationAgentlessButton');
return await testSubjects.exists(TEST_IDS.LAUNCH_CLOUD_FORMATION_AGENTLESS_BUTTON);
},
};
const cisGcp = {
isPostInstallGoogleCloudShellModal: async (isOrg: boolean, orgID?: string, prjID?: string) => {
const googleCloudShellModal = await testSubjects.find('postInstallGoogleCloudShellModal');
const googleCloudShellModal = await testSubjects.find(
TEST_IDS.POST_INSTALL_GOOGLE_CLOUD_SHELL_MODAL
);
const googleCloudShellModalVisibleText = await googleCloudShellModal.getVisibleText();
const stringProjectId = prjID ? prjID : '<PROJECT_ID>';
const stringOrganizationId = orgID ? `ORG_ID=${orgID}` : 'ORG_ID=<ORGANIZATION_ID>';
@ -81,14 +110,14 @@ export function AddCisIntegrationFormPageProvider({
getFieldValueInEditPage: async (field: string) => {
/* Newly added/edited integration always shows up on top by default as such we can just always click the most top if we want to check for the latest one */
const integrationList = await testSubjects.findAll('integrationNameLink');
const integrationList = await testSubjects.findAll(TEST_IDS.INTEGRATION_NAME_LINK);
await integrationList[0].click();
const fieldValue = await (await testSubjects.find(field)).getAttribute('value');
return fieldValue;
},
doesStringExistInCodeBlock: async (str: string) => {
const flyout = await testSubjects.find('agentEnrollmentFlyout');
const flyout = await testSubjects.find(TEST_IDS.AGENT_ENROLLMENT_FLYOUT);
const codeBlock = await flyout.findByXpath('//code');
const commandsToBeCopied = await codeBlock.getVisibleText();
return commandsToBeCopied.includes(str);
@ -96,7 +125,7 @@ export function AddCisIntegrationFormPageProvider({
getFieldValueInAddAgentFlyout: async (field: string, value: string) => {
/* Newly added/edited integration always shows up on top by default as such we can just always click the most top if we want to check for the latest one */
const integrationList = await testSubjects.findAll('agentEnrollmentFlyout');
const integrationList = await testSubjects.findAll(TEST_IDS.AGENT_ENROLLMENT_FLYOUT);
await integrationList[0].click();
await PageObjects.header.waitUntilLoadingHasFinished();
const fieldValue = (await (await testSubjects.find(field)).getAttribute(value)) ?? '';
@ -108,7 +137,7 @@ export function AddCisIntegrationFormPageProvider({
};
const isRadioButtonChecked = async (selector: string) => {
const page = await testSubjects.find('dataCollectionSetupStep');
const page = await testSubjects.find(TEST_IDS.DATA_COLLECTION_SETUP_STEP);
const findCheckedButton = await page.findAllByCssSelector(`input[id="${selector}"]:checked`);
if (findCheckedButton.length === 0) return false;
return true;
@ -116,7 +145,7 @@ export function AddCisIntegrationFormPageProvider({
const getUrlOnPostInstallModal = async () => {
/* Newly added/edited integration always shows up on top by default as such we can just always click the most top if we want to check for the latest one */
const fieldValue = await (await testSubjects.find('externalLink')).getAttribute('href');
const fieldValue = await (await testSubjects.find(TEST_IDS.EXTERNAL_LINK)).getAttribute('href');
return fieldValue;
};
@ -199,11 +228,11 @@ export function AddCisIntegrationFormPageProvider({
};
const navigateToEditIntegrationPage = async () => {
await testSubjects.click('integrationNameLink');
await testSubjects.click(TEST_IDS.INTEGRATION_NAME_LINK);
};
const navigateToEditAgentlessIntegrationPage = async () => {
await testSubjects.click('agentlessIntegrationNameLink');
await testSubjects.click(TEST_IDS.AGENTLESS_INTEGRATION_NAME_LINK);
};
const navigateToAddIntegrationKspmPage = async (space?: string) => {
@ -237,18 +266,18 @@ export function AddCisIntegrationFormPageProvider({
};
const clickPolicyToBeEdited = async (name: string) => {
const table = await testSubjects.find('integrationPolicyTable');
const table = await testSubjects.find(TEST_IDS.INTEGRATION_POLICY_TABLE);
const integrationToBeEdited = await table.findByXpath(`//text()="${name}"`);
await integrationToBeEdited.click();
};
const clickFirstElementOnIntegrationTable = async () => {
const integrationList = await testSubjects.findAll('integrationNameLink');
const integrationList = await testSubjects.findAll(TEST_IDS.INTEGRATION_NAME_LINK);
await integrationList[0].click();
};
const clickFirstElementOnIntegrationTableAddAgent = async () => {
const integrationList = await testSubjects.findAll('addAgentButton');
const integrationList = await testSubjects.findAll(TEST_IDS.ADD_AGENT_BUTTON);
await integrationList[0].click();
};
@ -264,11 +293,11 @@ export function AddCisIntegrationFormPageProvider({
return currentUrl;
};
const getIntegrationFormEntirePage = () => testSubjects.find('dataCollectionSetupStep');
const getIntegrationFormEntirePage = () => testSubjects.find(TEST_IDS.DATA_COLLECTION_SETUP_STEP);
const getIntegrationPolicyTable = () => testSubjects.find('integrationPolicyTable');
const getIntegrationPolicyTable = () => testSubjects.find(TEST_IDS.INTEGRATION_POLICY_TABLE);
const getIntegrationFormEditPage = () => testSubjects.find('editPackagePolicy_page');
const getIntegrationFormEditPage = () => testSubjects.find(TEST_IDS.EDIT_PACKAGE_POLICY_PAGE);
const findOptionInPage = async (text: string) => {
await PageObjects.header.waitUntilLoadingHasFinished();
@ -312,21 +341,24 @@ export function AddCisIntegrationFormPageProvider({
};
const clickSaveButton = async () => {
const optionToBeClicked = await findOptionInPage('createPackagePolicySaveButton');
const optionToBeClicked = await findOptionInPage(TEST_IDS.CREATE_PACKAGE_POLICY_SAVE_BUTTON);
await optionToBeClicked.click();
};
const waitUntilLaunchCloudFormationButtonAppears = async () =>
await testSubjects.exists(TEST_IDS.CONFIRM_CLOUD_FORMATION_MODAL_CONFIRM_BUTTON);
const clickSaveIntegrationButton = async () => {
const optionToBeClicked = await findOptionInPage('saveIntegration');
const optionToBeClicked = await findOptionInPage(TEST_IDS.SAVE_INTEGRATION);
await optionToBeClicked.click();
};
const getPostInstallModal = async () => {
return await testSubjects.find('confirmModalTitleText');
return await testSubjects.find(TEST_IDS.CONFIRM_MODAL_TITLE_TEXT);
};
const checkIntegrationPliAuthBlockExists = async () => {
return await testSubjects.exists('cloud-security-posture-integration-pli-auth-block');
return await testSubjects.exists(TEST_IDS.CLOUD_SECURITY_POSTURE_PLI_AUTH_BLOCK);
};
const fillInTextField = async (selector: string, text: string) => {
@ -343,7 +375,7 @@ export function AddCisIntegrationFormPageProvider({
};
const doesStringExistInCodeBlock = async (str: string) => {
const flyout = await testSubjects.find('agentEnrollmentFlyout');
const flyout = await testSubjects.find(TEST_IDS.AGENT_ENROLLMENT_FLYOUT);
const codeBlock = await flyout.findByXpath('//code');
const commandsToBeCopied = await codeBlock.getVisibleText();
return commandsToBeCopied.includes(str);
@ -351,7 +383,7 @@ export function AddCisIntegrationFormPageProvider({
const getFieldValueInAddAgentFlyout = async (field: string, value: string) => {
/* Newly added/edited integration always shows up on top by default as such we can just always click the most top if we want to check for the latest one */
const integrationList = await testSubjects.findAll('agentEnrollmentFlyout');
const integrationList = await testSubjects.findAll(TEST_IDS.AGENT_ENROLLMENT_FLYOUT);
await integrationList[0].click();
await PageObjects.header.waitUntilLoadingHasFinished();
const fieldValue = await (await testSubjects.find(field)).getAttribute(value);
@ -378,13 +410,13 @@ export function AddCisIntegrationFormPageProvider({
};
const inputUniqueIntegrationName = async () => {
const flyout = await testSubjects.find('createPackagePolicy_page');
const flyout = await testSubjects.find(TEST_IDS.CREATE_PACKAGE_POLICY_PAGE);
const nameField = await flyout.findAllByCssSelector('input[id="name"]');
await nameField[0].type(uuidv4());
};
const inputIntegrationName = async (text: string) => {
const page = await testSubjects.find('createPackagePolicy_page');
const page = await testSubjects.find(TEST_IDS.CREATE_PACKAGE_POLICY_PAGE);
const nameField = await page.findAllByCssSelector('input[id="name"]');
await nameField[0].clearValueWithKeyboard();
await nameField[0].type(text);
@ -486,7 +518,7 @@ export function AddCisIntegrationFormPageProvider({
await PageObjects.header.waitUntilLoadingHasFinished();
// Check if the Direct Access Key is updated package policy api with successful toast
expect(await testSubjects.exists('policyUpdateSuccessToast')).to.be(true);
expect(await testSubjects.exists(TEST_IDS.POLICY_UPDATE_SUCCESS_TOAST)).to.be(true);
await navigateToEditAgentlessIntegrationPage();
await PageObjects.header.waitUntilLoadingHasFinished();
@ -497,29 +529,29 @@ export function AddCisIntegrationFormPageProvider({
};
const getFirstCspmIntegrationPageIntegration = async () => {
const integration = await testSubjects.find('integrationNameLink');
const integration = await testSubjects.find(TEST_IDS.INTEGRATION_NAME_LINK);
return await integration.getVisibleText();
};
const getFirstCspmIntegrationPageAgentlessIntegration = async () => {
const integration = await testSubjects.find('agentlessIntegrationNameLink');
const integration = await testSubjects.find(TEST_IDS.AGENTLESS_INTEGRATION_NAME_LINK);
return await integration.getVisibleText();
};
const getFirstCspmIntegrationPageAgent = async () => {
const agent = await testSubjects.find('agentPolicyNameLink');
const agent = await testSubjects.find(TEST_IDS.AGENT_POLICY_NAME_LINK);
// this is assuming that the agent was just created therefor should be the first element
return await agent.getVisibleText();
};
const getFirstCspmIntegrationPageAgentlessStatus = async () => {
const agent = await testSubjects.find('agentlessStatusBadge');
const agent = await testSubjects.find(TEST_IDS.AGENTLESS_STATUS_BADGE);
// this is assuming that the agent was just created therefor should be the first element
return await agent.getVisibleText();
};
const getAgentBasedPolicyValue = async () => {
const agentName = await testSubjects.find('createAgentPolicyNameField');
const agentName = await testSubjects.find(TEST_IDS.CREATE_AGENT_POLICY_NAME_FIELD);
return await agentName.getAttribute('value');
};
@ -604,5 +636,6 @@ export function AddCisIntegrationFormPageProvider({
navigateToEditIntegrationPage,
navigateToEditAgentlessIntegrationPage,
closeAllOpenTabs,
waitUntilLaunchCloudFormationButtonAppears,
};
}

View file

@ -37,7 +37,7 @@ export default function (providerContext: FtrProviderContext) {
await cisIntegration.inputUniqueIntegrationName();
await pageObjects.header.waitUntilLoadingHasFinished();
await cisIntegration.clickSaveButton();
await pageObjects.header.waitUntilLoadingHasFinished();
await cisIntegration.waitUntilLaunchCloudFormationButtonAppears();
expect(
(await cisIntegration.getUrlOnPostInstallModal()) ===
'https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-whatis-howdoesitwork.html'