From 30fc76e1abde3953a8eb0ffd1956dec0df546ee3 Mon Sep 17 00:00:00 2001 From: Yonas Berhe Date: Tue, 10 Dec 2024 12:26:18 -0800 Subject: [PATCH] automation: assign cluster to fleet workspace --- .../e2e/po/components/assign-to-dialog.po.ts | 23 ++++++ .../pages/fleet/fleet.cattle.io.cluster.po.ts | 5 ++ .../tests/pages/fleet/fleet-clusters.spec.ts | 78 ++++++++++++++++++- shell/components/AssignTo.vue | 1 + 4 files changed, 105 insertions(+), 2 deletions(-) create mode 100644 cypress/e2e/po/components/assign-to-dialog.po.ts diff --git a/cypress/e2e/po/components/assign-to-dialog.po.ts b/cypress/e2e/po/components/assign-to-dialog.po.ts new file mode 100644 index 00000000000..212e22f5838 --- /dev/null +++ b/cypress/e2e/po/components/assign-to-dialog.po.ts @@ -0,0 +1,23 @@ +import ComponentPo from '@/cypress/e2e/po/components/component.po'; +import AsyncButtonPo from '@/cypress/e2e/po/components/async-button.po'; +import LabeledSelectPo from '@/cypress/e2e/po/components/labeled-select.po'; + +export default class AssignToDialogPo extends ComponentPo { + constructor(selector = '[data-testid="card"]') { + super(selector); + } + + workspaceSelect(): LabeledSelectPo { + return new LabeledSelectPo('[data-testid="workspace_options"]'); + } + + applyButton() { + return new AsyncButtonPo('[data-testid="action-button-async-button"]', this.self()); + } + + applyAndWait(endpoint: string) { + cy.intercept('PUT', endpoint).as(endpoint); + this.applyButton().click(); + cy.wait(`@${ endpoint }`).its('response.statusCode').should('eq', 200); + } +} diff --git a/cypress/e2e/po/pages/fleet/fleet.cattle.io.cluster.po.ts b/cypress/e2e/po/pages/fleet/fleet.cattle.io.cluster.po.ts index b0a1232b500..0874a0488f7 100644 --- a/cypress/e2e/po/pages/fleet/fleet.cattle.io.cluster.po.ts +++ b/cypress/e2e/po/pages/fleet/fleet.cattle.io.cluster.po.ts @@ -3,6 +3,7 @@ import FleetClusterList from '@/cypress/e2e/po/lists/fleet/fleet.cattle.io.clust import { FleetDashboardPagePo } from '@/cypress/e2e/po/pages/fleet/fleet-dashboard.po'; import ProductNavPo from '@/cypress/e2e/po/side-bars/product-side-nav.po'; import FleetClusterEditPo from '@/cypress/e2e/po/edit/fleet/fleet.cattle.io.cluster.po'; +import AssignToDialogPo from '@/cypress/e2e/po/components/assign-to-dialog.po'; export class FleetClusterListPagePo extends PagePo { static url = `/c/_/fleet/fleet.cattle.io.cluster` @@ -49,4 +50,8 @@ export class FleetClusterListPagePo extends PagePo { editFleetCluster(workspace: string, clusterName: string): FleetClusterEditPo { return new FleetClusterEditPo(workspace, clusterName); } + + changeWorkspaceForm(): AssignToDialogPo { + return new AssignToDialogPo(); + } } diff --git a/cypress/e2e/tests/pages/fleet/fleet-clusters.spec.ts b/cypress/e2e/tests/pages/fleet/fleet-clusters.spec.ts index 601753b44df..12eca5f170c 100644 --- a/cypress/e2e/tests/pages/fleet/fleet-clusters.spec.ts +++ b/cypress/e2e/tests/pages/fleet/fleet-clusters.spec.ts @@ -10,11 +10,13 @@ import * as jsyaml from 'js-yaml'; import { HeaderPo } from '@/cypress/e2e/po/components/header.po'; import { GitRepoCreatePo } from '@/cypress/e2e/po/pages/fleet/gitrepo-create.po'; import { LONG_TIMEOUT_OPT, MEDIUM_TIMEOUT_OPT } from '@/cypress/support/utils/timeouts'; +import { FeatureFlagsPagePo } from '@/cypress/e2e/po/pages/global-settings/feature-flags.po'; describe('Fleet Clusters', { tags: ['@fleet', '@adminUser'] }, () => { const fleetClusterListPage = new FleetClusterListPagePo(); const fleetGitRepoListPage = new FleetGitRepoListPagePo(); const clusterList = new ClusterManagerListPagePo(); + const featureFlagsPage = new FeatureFlagsPagePo(); const headerPo = new HeaderPo(); const gitRepoUrl = 'https://github.com/rancher/fleet-test-data'; const branch = 'master'; @@ -26,12 +28,20 @@ describe('Fleet Clusters', { tags: ['@fleet', '@adminUser'] }, () => { const namespace = 'fleet-default'; let removeCluster = false; let removeGitRepo = false; + let removeWorkspace = false; + let disableFeature = false; let clusterId = ''; let clusterName = ''; let gitRepo = ''; + let customWorkspace = ''; + const feature = 'provisioningv2-fleet-workspace-back-population'; before(() => { cy.login(); + cy.createE2EResourceName('fleet-workspace').then((name) => { + customWorkspace = name; + }); + cy.createE2EResourceName('git-repo').then((name) => { gitRepo = name; }); @@ -76,6 +86,8 @@ describe('Fleet Clusters', { tags: ['@fleet', '@adminUser'] }, () => { }); }); }); + + cy.updateNamespaceFilter('local', 'none', '{"local":["all://user"]}'); }); it('data is populated in fleet cluster list and detail view', () => { @@ -242,6 +254,54 @@ describe('Fleet Clusters', { tags: ['@fleet', '@adminUser'] }, () => { }); }); + it('can assign cluster to different fleet workspaces', () => { + // create workspace + cy.createRancherResource('v3', 'fleetworkspaces', `{"type":"fleetworkspace","name":"${ customWorkspace }","annotations":{},"labels":{}}`).then(() => { + removeWorkspace = true; + }); + + // enable feature: provisioningv2-fleet-workspace-back-population + FeatureFlagsPagePo.navTo(); + featureFlagsPage.waitForPage(); + featureFlagsPage.list().details(feature, 0).should('include.text', 'Disabled'); + featureFlagsPage.list().clickRowActionMenuItem(feature, 'Activate'); + featureFlagsPage.clickCardActionButtonAndWait('Activate', feature, true, { waitForModal: true, waitForRequest: true }); + featureFlagsPage.list().details(feature, 0).should('include.text', 'Active').then(() => { + disableFeature = true; + }); + + // go to fleet clusters + fleetClusterListPage.goTo(); + fleetClusterListPage.waitForPage(); + headerPo.selectWorkspace(namespace); + + cy.intercept('PUT', '/v1/userpreferences/*').as('changeWorkspace'); + fleetClusterListPage.clusterList().actionMenu(clusterName).getMenuItem('Change workspace').click(); + fleetClusterListPage.changeWorkspaceForm().workspaceSelect().toggle(); + fleetClusterListPage.changeWorkspaceForm().workspaceSelect().clickOptionWithLabel(customWorkspace); + fleetClusterListPage.changeWorkspaceForm().applyAndWait('v3/clusters/*'); + fleetClusterListPage.sortableTable().checkRowCount(true, 1, MEDIUM_TIMEOUT_OPT); + + FleetClusterListPagePo.navTo(); + fleetClusterListPage.waitForPage(); + headerPo.selectWorkspace(customWorkspace); + cy.wait('@changeWorkspace'); + fleetClusterListPage.clusterList().details(clusterName, 2).isVisible(); + + // restore + fleetClusterListPage.clusterList().actionMenu(clusterName).getMenuItem('Change workspace').click(); + fleetClusterListPage.changeWorkspaceForm().workspaceSelect().toggle(); + fleetClusterListPage.changeWorkspaceForm().workspaceSelect().clickOptionWithLabel(namespace); + fleetClusterListPage.changeWorkspaceForm().applyAndWait('v3/clusters/*'); + fleetClusterListPage.sortableTable().checkRowCount(true, 1, MEDIUM_TIMEOUT_OPT); + + FleetClusterListPagePo.navTo(); + fleetClusterListPage.waitForPage(); + headerPo.selectWorkspace(namespace); + cy.wait('@changeWorkspace'); + fleetClusterListPage.clusterList().details(clusterName, 2).isVisible(); + }); + it('removing git repo should remove bundles on downstream cluster (deployments removed)', () => { const deploymentsList = new WorkloadsDeploymentsListPagePo(clusterId); @@ -253,7 +313,7 @@ describe('Fleet Clusters', { tags: ['@fleet', '@adminUser'] }, () => { deploymentsList.goTo(); deploymentsList.waitForPage(); deploymentsList.sortableTable().checkLoadingIndicatorNotVisible(); - deploymentsList.sortableTable().checkRowCount(true, 1); + deploymentsList.sortableTable().checkRowCount(true, 1, MEDIUM_TIMEOUT_OPT); }); it('cluster should be removed from fleet cluster list once deleted', () => { @@ -267,7 +327,7 @@ describe('Fleet Clusters', { tags: ['@fleet', '@adminUser'] }, () => { fleetClusterListPage.waitForPage(); headerPo.selectWorkspace(namespace); fleetClusterListPage.sortableTable().checkLoadingIndicatorNotVisible(); - fleetClusterListPage.sortableTable().checkRowCount(true, 1); + fleetClusterListPage.sortableTable().checkRowCount(true, 1, MEDIUM_TIMEOUT_OPT); }); after('clean up', () => { @@ -279,6 +339,20 @@ describe('Fleet Clusters', { tags: ['@fleet', '@adminUser'] }, () => { // delete gitrepo cy.deleteRancherResource('v1', `fleet.cattle.io.gitrepos/${ namespace }`, gitRepo, false); } + if (removeWorkspace) { + // delete workspace + cy.deleteRancherResource('v3', 'fleetWorkspaces', customWorkspace, false); + } + + if (disableFeature) { + // disable feature: provisioningv2-fleet-workspace-back-population + FeatureFlagsPagePo.navTo(); + featureFlagsPage.waitForPage(); + featureFlagsPage.list().details(feature, 0).should('include.text', 'Active'); + featureFlagsPage.list().clickRowActionMenuItem(feature, 'Deactivate'); + featureFlagsPage.clickCardActionButtonAndWait('Deactivate', feature, false, { waitForModal: true, waitForRequest: true }); + featureFlagsPage.list().details(feature, 0).should('include.text', 'Disabled'); + } }); }); diff --git a/shell/components/AssignTo.vue b/shell/components/AssignTo.vue index ff411eea6cf..e34c4701712 100644 --- a/shell/components/AssignTo.vue +++ b/shell/components/AssignTo.vue @@ -132,6 +132,7 @@ export default {