diff --git a/cypress/e2e/tests/pages/fleet/fleet-clusters.spec.ts b/cypress/e2e/tests/pages/fleet/fleet-clusters.spec.ts index 564f27a07f2..4e060304fb1 100644 --- a/cypress/e2e/tests/pages/fleet/fleet-clusters.spec.ts +++ b/cypress/e2e/tests/pages/fleet/fleet-clusters.spec.ts @@ -9,6 +9,7 @@ import * as jsyaml from 'js-yaml'; import { HeaderPo } from '@/cypress/e2e/po/components/header.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'; +import LoadingPo from '@/cypress/e2e/po/components/loading.po'; const fleetClusterListPage = new FleetClusterListPagePo(); const fleetAppBundlesListPage = new FleetApplicationListPagePo(); @@ -44,7 +45,7 @@ describe('Fleet Clusters - bundle manifests are deployed from the BundleDeployme gitRepo = name; }); - cy.createE2EResourceName('rke2cluster').then((name) => { + cy.createE2EResourceName('fleetrke2cluster').then((name) => { clusterName = name; // create real cluster @@ -277,32 +278,41 @@ describe('Fleet Clusters - bundle manifests are deployed from the BundleDeployme disableFeature = true; }); + const loadingPo = new LoadingPo('.loading-indicator'); + // go to fleet clusters - fleetClusterListPage.goTo(); + FleetClusterListPagePo.navTo(); fleetClusterListPage.waitForPage(); + loadingPo.checkNotExists(MEDIUM_TIMEOUT_OPT); headerPo.selectWorkspace(namespace); + cy.intercept('GET', '/v3/clusters').as('getClusters'); cy.intercept('PUT', '/v1/userpreferences/*').as('changeWorkspace'); - fleetClusterListPage.list().actionMenu(clusterName).getMenuItem('Change workspace') - .click(); - fleetClusterListPage.changeWorkspaceForm().workspaceSelect().toggle(); - fleetClusterListPage.changeWorkspaceForm().workspaceSelect().clickOptionWithLabel(customWorkspace); - fleetClusterListPage.changeWorkspaceForm().applyAndWait('v3/clusters/*'); - fleetClusterListPage.list().resourceTable().sortableTable() - .checkRowCount(true, 1, MEDIUM_TIMEOUT_OPT); - - FleetClusterListPagePo.navTo(); - fleetClusterListPage.waitForPage(); - headerPo.selectWorkspace(customWorkspace); - cy.wait('@changeWorkspace'); - fleetClusterListPage.resourceTableDetails(clusterName, 2).isVisible(); - - // restore - fleetClusterListPage.list().actionMenu(clusterName).getMenuItem('Change workspace') - .click(); - fleetClusterListPage.changeWorkspaceForm().workspaceSelect().toggle(); - fleetClusterListPage.changeWorkspaceForm().workspaceSelect().clickOptionWithLabel(namespace); - fleetClusterListPage.changeWorkspaceForm().applyAndWait('v3/clusters/*'); + cy.getClusterIdByName(clusterName).then((clusterId) => { + fleetClusterListPage.list().actionMenu(clusterName).getMenuItem('Change workspace') + .should('exist') + .click(); + cy.wait('@getClusters'); + fleetClusterListPage.changeWorkspaceForm().workspaceSelect().toggle(); + fleetClusterListPage.changeWorkspaceForm().workspaceSelect().clickOptionWithLabel(customWorkspace); + fleetClusterListPage.changeWorkspaceForm().applyAndWait(`v3/clusters/${ clusterId }`); + fleetClusterListPage.list().resourceTable().sortableTable() + .checkRowCount(true, 1, MEDIUM_TIMEOUT_OPT); + + FleetClusterListPagePo.navTo(); + fleetClusterListPage.waitForPage(); + headerPo.selectWorkspace(customWorkspace); + cy.wait('@changeWorkspace'); + fleetClusterListPage.resourceTableDetails(clusterName, 2).isVisible(); + + // restore + fleetClusterListPage.list().actionMenu(clusterName).getMenuItem('Change workspace') + .should('exist') + .click(); + fleetClusterListPage.changeWorkspaceForm().workspaceSelect().toggle(); + fleetClusterListPage.changeWorkspaceForm().workspaceSelect().clickOptionWithLabel(namespace); + fleetClusterListPage.changeWorkspaceForm().applyAndWait(`v3/clusters/${ clusterId }`); + }); fleetClusterListPage.list().resourceTable().sortableTable() .checkRowCount(true, 1, MEDIUM_TIMEOUT_OPT); diff --git a/cypress/globals.d.ts b/cypress/globals.d.ts index 1900046f035..96f36339b29 100644 --- a/cypress/globals.d.ts +++ b/cypress/globals.d.ts @@ -94,6 +94,7 @@ declare global { createAmazonMachineConfig(instanceType: string, region: string, vpcId: string, zone: string, type: string, clusterName: string, namespace: string): Chainable; createAmazonRke2Cluster(params: CreateAmazonRke2ClusterParams): Chainable; createAmazonRke2ClusterWithoutMachineConfig(params: CreateAmazonRke2ClusterWithoutMachineConfigParams): Chainable; + getKubernetesReleases(rkeType: 'rke2' | 'k3s'): Chainable; createSecret(namespace: string, name: string, options?: { type?: string; metadata?: any; data?: any }): Chainable; createConfigMap(namespace: string, name: string, options?: { metadata?: any; data?: any }): Chainable; createService(namespace: string, name: string, options?: { type?: string; ports?: any[]; spec?: any; metadata?: any }): Chainable; diff --git a/cypress/support/commands/rancher-api-commands.ts b/cypress/support/commands/rancher-api-commands.ts index 9361121af62..95904a6facc 100644 --- a/cypress/support/commands/rancher-api-commands.ts +++ b/cypress/support/commands/rancher-api-commands.ts @@ -636,6 +636,22 @@ Cypress.Commands.add('deleteNodeTemplate', (nodeTemplateId, timeout = 30000, fai return retry(); }); +Cypress.Commands.add('getKubernetesReleases', (rkeType: 'rke2' | 'k3s') => { + return cy.request({ + method: 'GET', + url: `${ Cypress.env('api') }/v1-${ rkeType }-release/releases`, + headers: { + 'x-api-csrf': token.value, + Accept: 'application/json' + }, + }) + .then((resp) => { + expect(resp.status).to.eq(200); + + return resp; + }); +}); + /** * Create RKE2 cluster with Amazon EC2 cloud provider */ @@ -644,121 +660,128 @@ Cypress.Commands.add('createAmazonRke2Cluster', (params: CreateAmazonRke2Cluster machineConfig, rke2ClusterAmazon, cloudCredentialsAmazon, metadata } = params; - return cy.createAwsCloudCredentials(cloudCredentialsAmazon.workspace, cloudCredentialsAmazon.name, cloudCredentialsAmazon.region, cloudCredentialsAmazon.accessKey, cloudCredentialsAmazon.secretKey) - .then((resp: Cypress.Response) => { - const cloudCredentialId = resp.body.id; + return cy.getKubernetesReleases('rke2').then((resp: Cypress.Response) => { + // Get the latest kubernetes version + const kubernetesVersion = resp.body.data[resp.body.data.length - 1].id; - return cy.createAmazonMachineConfig( - machineConfig.instanceType, machineConfig.region, machineConfig.vpcId, machineConfig.zone, machineConfig.type, machineConfig.clusterName, machineConfig.namespace) - .then((resp: Cypress.Response) => { - const machineConfigId = resp.body.id.split('/'); - - return cy.request({ - method: 'POST', - url: `${ Cypress.env('api') }/v1/provisioning.cattle.io.clusters`, - failOnStatusCode: true, - headers: { - 'x-api-csrf': token.value, - Accept: 'application/json' - }, - body: { - type: 'provisioning.cattle.io.cluster', - metadata: { - namespace: rke2ClusterAmazon.namespace, - annotations: { - 'field.cattle.io/description': `${ rke2ClusterAmazon.clusterName }-description`, - ...(metadata?.annotations || {}), - }, - labels: metadata?.labels || {}, - name: rke2ClusterAmazon.clusterName + cy.log(`kubernetesVersion: ${ kubernetesVersion }`); + + return cy.createAwsCloudCredentials(cloudCredentialsAmazon.workspace, cloudCredentialsAmazon.name, cloudCredentialsAmazon.region, cloudCredentialsAmazon.accessKey, cloudCredentialsAmazon.secretKey) + .then((resp: Cypress.Response) => { + const cloudCredentialId = resp.body.id; + + return cy.createAmazonMachineConfig( + machineConfig.instanceType, machineConfig.region, machineConfig.vpcId, machineConfig.zone, machineConfig.type, machineConfig.clusterName, machineConfig.namespace) + .then((resp: Cypress.Response) => { + const machineConfigId = resp.body.id.split('/'); + + return cy.request({ + method: 'POST', + url: `${ Cypress.env('api') }/v1/provisioning.cattle.io.clusters`, + failOnStatusCode: true, + headers: { + 'x-api-csrf': token.value, + Accept: 'application/json' }, - spec: { - rkeConfig: { - chartValues: { 'rke2-calico': {} }, - upgradeStrategy: { - controlPlaneConcurrency: '1', - controlPlaneDrainOptions: { - deleteEmptyDirData: true, - disableEviction: false, - enabled: false, - force: false, - gracePeriod: -1, - ignoreDaemonSets: true, - skipWaitForDeleteTimeoutSeconds: 0, - timeout: 120 - }, - workerConcurrency: '1', - workerDrainOptions: { - deleteEmptyDirData: true, - disableEviction: false, - enabled: false, - force: false, - gracePeriod: -1, - ignoreDaemonSets: true, - skipWaitForDeleteTimeoutSeconds: 0, - timeout: 120 - } - }, - dataDirectories: { - systemAgent: '', - provisioning: '', - k8sDistro: '' + body: { + type: 'provisioning.cattle.io.cluster', + metadata: { + namespace: rke2ClusterAmazon.namespace, + annotations: { + 'field.cattle.io/description': `${ rke2ClusterAmazon.clusterName }-description`, + ...(metadata?.annotations || {}), }, - machineGlobalConfig: { - cni: 'calico', - 'disable-kube-proxy': false, - 'etcd-expose-metrics': false + labels: metadata?.labels || {}, + name: rke2ClusterAmazon.clusterName + }, + spec: { + rkeConfig: { + chartValues: { 'rke2-calico': {} }, + upgradeStrategy: { + controlPlaneConcurrency: '1', + controlPlaneDrainOptions: { + deleteEmptyDirData: true, + disableEviction: false, + enabled: false, + force: false, + gracePeriod: -1, + ignoreDaemonSets: true, + skipWaitForDeleteTimeoutSeconds: 0, + timeout: 120 + }, + workerConcurrency: '1', + workerDrainOptions: { + deleteEmptyDirData: true, + disableEviction: false, + enabled: false, + force: false, + gracePeriod: -1, + ignoreDaemonSets: true, + skipWaitForDeleteTimeoutSeconds: 0, + timeout: 120 + } + }, + dataDirectories: { + systemAgent: '', + provisioning: '', + k8sDistro: '' + }, + machineGlobalConfig: { + cni: 'calico', + 'disable-kube-proxy': false, + 'etcd-expose-metrics': false + }, + machineSelectorConfig: [ + { config: { 'protect-kernel-defaults': false } } + ], + etcd: { + disableSnapshots: false, + s3: null, + snapshotRetention: 5, + snapshotScheduleCron: '0 */5 * * *' + }, + registries: { + configs: {}, + mirrors: {} + }, + machinePools: [ + { + name: 'pool1', + etcdRole: true, + controlPlaneRole: true, + workerRole: true, + hostnamePrefix: '', + labels: {}, + quantity: 3, + unhealthyNodeTimeout: '0m', + machineConfigRef: { + kind: 'Amazonec2Config', + name: machineConfigId[1] + }, + drainBeforeDelete: true + } + ] }, machineSelectorConfig: [ - { config: { 'protect-kernel-defaults': false } } + { config: {} } ], - etcd: { - disableSnapshots: false, - s3: null, - snapshotRetention: 5, - snapshotScheduleCron: '0 */5 * * *' - }, - registries: { - configs: {}, - mirrors: {} - }, - machinePools: [ - { - name: 'pool1', - etcdRole: true, - controlPlaneRole: true, - workerRole: true, - hostnamePrefix: '', - labels: {}, - quantity: 3, - unhealthyNodeTimeout: '0m', - machineConfigRef: { - kind: 'Amazonec2Config', - name: machineConfigId[1] - }, - drainBeforeDelete: true - } - ] - }, - machineSelectorConfig: [ - { config: {} } - ], - kubernetesVersion: 'v1.29.4+rke2r1', - defaultPodSecurityAdmissionConfigurationTemplateName: '', - cloudCredentialSecretName: cloudCredentialId, - localClusterAuthEndpoint: { - enabled: false, - caCerts: '', - fqdn: '' + kubernetesVersion, + defaultPodSecurityAdmissionConfigurationTemplateName: '', + cloudCredentialSecretName: cloudCredentialId, + localClusterAuthEndpoint: { + enabled: false, + caCerts: '', + fqdn: '' + } } } - } - }) - .then((resp: Cypress.Response) => { - expect(resp.status).to.eq(201); - }); - }); - }); + }) + .then((resp: Cypress.Response) => { + expect(resp.status).to.eq(201); + }); + }); + }); + }); }); /**