From 6c5b70c759eb9d501f02faf6282ae195493afd94 Mon Sep 17 00:00:00 2001 From: Alexandre Alves Date: Wed, 24 Apr 2024 15:15:04 +0100 Subject: [PATCH 1/4] add e2e test for issue --- .../e2e/tests/pages/explorer/workloads/daemonsets.spec.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cypress/e2e/tests/pages/explorer/workloads/daemonsets.spec.ts b/cypress/e2e/tests/pages/explorer/workloads/daemonsets.spec.ts index bf40d59d8da..1ec94e45eb2 100644 --- a/cypress/e2e/tests/pages/explorer/workloads/daemonsets.spec.ts +++ b/cypress/e2e/tests/pages/explorer/workloads/daemonsets.spec.ts @@ -8,13 +8,18 @@ describe('Cluster Explorer', { tags: ['@explorer', '@adminUser'] }, () => { generateFakeClusterDataAndIntercepts(fakeProvClusterId, fakeMgmtClusterId); // to test payload of https://github.com/rancher/dashboard/issues/9874 +<<<<<<< HEAD cy.intercept('PUT', `k8s/clusters/${ fakeMgmtClusterId }/v1/apps.daemonsets/calico-system/calico-node`, (req: any) => { +======= + cy.intercept('PUT', 'k8s/clusters/some-fake-mgmt-id/v1/apps.daemonsets/calico-system/calico-node', (req: any) => { +>>>>>>> 710cc8c9b7 (add e2e test for issue) req.reply({ statusCode: 200, body: {} }); }).as('daemonsetEdit'); +<<<<<<< HEAD // to prevent error when rendering the daemonsets list after save (otherwise test will fail) cy.intercept('GET', `k8s/clusters/${ fakeMgmtClusterId }/v1/nodes`, (req: any) => { req.reply({ @@ -23,6 +28,8 @@ describe('Cluster Explorer', { tags: ['@explorer', '@adminUser'] }, () => { }); }).as('nodesReq'); +======= +>>>>>>> 710cc8c9b7 (add e2e test for issue) cy.login(); }); From ff4ad1e1d920f7d65603137f259d0da19c999384 Mon Sep 17 00:00:00 2001 From: Alexandre Alves Date: Mon, 29 Apr 2024 12:23:05 +0100 Subject: [PATCH 2/4] fix e2e issue --- cypress/e2e/tests/pages/explorer/workloads/daemonsets.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cypress/e2e/tests/pages/explorer/workloads/daemonsets.spec.ts b/cypress/e2e/tests/pages/explorer/workloads/daemonsets.spec.ts index 1ec94e45eb2..8cecc277be1 100644 --- a/cypress/e2e/tests/pages/explorer/workloads/daemonsets.spec.ts +++ b/cypress/e2e/tests/pages/explorer/workloads/daemonsets.spec.ts @@ -15,7 +15,7 @@ describe('Cluster Explorer', { tags: ['@explorer', '@adminUser'] }, () => { >>>>>>> 710cc8c9b7 (add e2e test for issue) req.reply({ statusCode: 200, - body: {} + body: { value: {} } }); }).as('daemonsetEdit'); From 87030222c5dea98530d2553d1249f0bb205d34de Mon Sep 17 00:00:00 2001 From: Alexandre Alves Date: Mon, 29 Apr 2024 14:07:19 +0100 Subject: [PATCH 3/4] fix e2e issue with nodes req when entering daemonsets list view --- .../tests/pages/explorer/workloads/daemonsets.spec.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/cypress/e2e/tests/pages/explorer/workloads/daemonsets.spec.ts b/cypress/e2e/tests/pages/explorer/workloads/daemonsets.spec.ts index 8cecc277be1..bf40d59d8da 100644 --- a/cypress/e2e/tests/pages/explorer/workloads/daemonsets.spec.ts +++ b/cypress/e2e/tests/pages/explorer/workloads/daemonsets.spec.ts @@ -8,18 +8,13 @@ describe('Cluster Explorer', { tags: ['@explorer', '@adminUser'] }, () => { generateFakeClusterDataAndIntercepts(fakeProvClusterId, fakeMgmtClusterId); // to test payload of https://github.com/rancher/dashboard/issues/9874 -<<<<<<< HEAD cy.intercept('PUT', `k8s/clusters/${ fakeMgmtClusterId }/v1/apps.daemonsets/calico-system/calico-node`, (req: any) => { -======= - cy.intercept('PUT', 'k8s/clusters/some-fake-mgmt-id/v1/apps.daemonsets/calico-system/calico-node', (req: any) => { ->>>>>>> 710cc8c9b7 (add e2e test for issue) req.reply({ statusCode: 200, - body: { value: {} } + body: {} }); }).as('daemonsetEdit'); -<<<<<<< HEAD // to prevent error when rendering the daemonsets list after save (otherwise test will fail) cy.intercept('GET', `k8s/clusters/${ fakeMgmtClusterId }/v1/nodes`, (req: any) => { req.reply({ @@ -28,8 +23,6 @@ describe('Cluster Explorer', { tags: ['@explorer', '@adminUser'] }, () => { }); }).as('nodesReq'); -======= ->>>>>>> 710cc8c9b7 (add e2e test for issue) cy.login(); }); From c35b5b7d7ca9ddb445e3f05a12d46cd266e8dc51 Mon Sep 17 00:00:00 2001 From: Alexandre Alves Date: Mon, 29 Apr 2024 11:23:02 +0100 Subject: [PATCH 4/4] update fake-cluster logic on e2e to allow for fake cluster edit config + add e2e for 10412 --- cypress/e2e/blueprints/nav/edit-cluster.ts | 348 ++++++++++++++++++ cypress/e2e/blueprints/nav/fake-cluster.ts | 188 +++++++++- .../edit/cluster-edit-generic.po.ts | 17 +- .../pages/manager/edit-fake-cluster.spec.ts | 42 +++ .../tabs/registries/RegistryConfigs.vue | 1 + 5 files changed, 587 insertions(+), 9 deletions(-) create mode 100644 cypress/e2e/blueprints/nav/edit-cluster.ts create mode 100644 cypress/e2e/tests/pages/manager/edit-fake-cluster.spec.ts diff --git a/cypress/e2e/blueprints/nav/edit-cluster.ts b/cypress/e2e/blueprints/nav/edit-cluster.ts new file mode 100644 index 00000000000..49ac529fed3 --- /dev/null +++ b/cypress/e2e/blueprints/nav/edit-cluster.ts @@ -0,0 +1,348 @@ +// /v1/management.cattle.io.nodedrivers?* +export function generateFakeNodeDriversReply():any { + return { + id: 'digitalocean', + type: 'management.cattle.io.nodedriver', + links: { + remove: 'blocked', + self: 'https://localhost:8005/v1/management.cattle.io.nodedrivers/digitalocean', + update: 'blocked', + view: 'https://localhost:8005/v1/management.cattle.io.nodedrivers/digitalocean' + }, + apiVersion: 'management.cattle.io/v3', + kind: 'NodeDriver', + metadata: { + annotations: { + 'io.cattle.nodedriver/ui-field-hints': '{"sshKeyContents":{"type":"multiline"},"userdata":{"type":"multiline"}}', + 'lifecycle.cattle.io/create.node-driver-controller': 'true', + privateCredentialFields: 'accessToken' + }, + creationTimestamp: '2024-04-12T08:53:37Z', + fields: [ + 'digitalocean', + '12d' + ], + finalizers: [ + 'controller.cattle.io/node-driver-controller' + ], + generation: 4, + labels: { 'cattle.io/creator': 'norman' }, + name: 'digitalocean', + relationships: [ + { + toId: 'digitaloceancredentialconfig', + toType: 'management.cattle.io.dynamicschema', + rel: 'owner', + state: 'active', + message: 'Resource is current' + }, + { + toId: 'digitaloceanconfig', + toType: 'management.cattle.io.dynamicschema', + rel: 'owner', + state: 'active', + message: 'Resource is current' + } + ], + resourceVersion: '2429', + state: { + error: false, + message: '', + name: 'active', + transitioning: false + }, + uid: '611dbaa1-9ba4-463f-ad61-12c2b879fbad' + }, + spec: { + active: true, + addCloudCredential: false, + builtin: true, + checksum: '', + description: '', + displayName: 'digitalocean', + externalId: '', + uiUrl: '', + url: 'local://', + whitelistDomains: [ + 'api.digitalocean.com' + ] + }, + status: { + appliedChecksum: '', + appliedDockerMachineVersion: 'rancher-machine version v0.15.0-rancher109, build 11ea4b32\n', + appliedURL: '', + conditions: [ + { + error: false, + lastUpdateTime: '2024-04-12T08:53:41Z', + status: 'True', + transitioning: false, + type: 'Downloaded' + }, + { + error: false, + lastUpdateTime: '2024-04-12T08:53:41Z', + status: 'True', + transitioning: false, + type: 'Installed' + }, + { + error: false, + lastUpdateTime: '2024-04-12T08:53:52Z', + status: 'True', + transitioning: false, + type: 'Active' + }, + { + error: false, + lastUpdateTime: '2024-04-12T08:53:52Z', + status: 'True', + transitioning: false, + type: 'Inactive' + } + ] + } + }; +} + +// /v3/cloudcredentials +export function generateFakeCloudCredentialsReply(cloudCredId:string):any { + return { + type: 'collection', + links: { self: 'https://localhost:8005/v3/cloudcredentials' }, + createTypes: { cloudCredential: 'https://localhost:8005/v3/cloudcredentials' }, + actions: {}, + pagination: { + limit: 1000, + total: 1 + }, + sort: { + order: 'asc', + reverse: 'https://localhost:8005/v3/cloudcredentials?order=desc', + links: { + description: 'https://localhost:8005/v3/cloudcredentials?sort=description', + name: 'https://localhost:8005/v3/cloudcredentials?sort=name', + uuid: 'https://localhost:8005/v3/cloudcredentials?sort=uuid' + } + }, + filters: { + created: null, + creatorId: null, + description: null, + id: null, + name: null, + removed: null, + uuid: null + }, + resourceType: 'cloudCredential', + data: [ + { + annotations: {}, + baseType: 'cloudCredential', + created: '2024-04-23T11:57:20Z', + createdTS: 1713873440000, + creatorId: 'user-ghfld', + digitaloceancredentialConfig: {}, + id: `cattle-global-data:cc-${ cloudCredId }`, + labels: { 'cattle.io/creator': 'norman' }, + links: { + nodeTemplates: `https://localhost:8005/v3/nodeTemplates?cloudCredentialId=cattle-global-data%3Acc-${ cloudCredId }`, + remove: `https://localhost:8005/v3/cloudCredentials/cattle-global-data:cc-${ cloudCredId }`, + self: `https://localhost:8005/v3/cloudCredentials/cattle-global-data:cc-${ cloudCredId }`, + update: `https://localhost:8005/v3/cloudCredentials/cattle-global-data:cc-${ cloudCredId }` + }, + name: 'test-do-creds', + type: 'cloudCredential', + uuid: 'e6e0e54b-9077-46d7-8aa7-b9231a955aed' + } + ] + }; +} + +export function generateFakeCloudCredIndividualReply(cloudCredId:string):any { + return { + annotations: {}, + baseType: 'cloudCredential', + created: '2024-04-23T11:57:20Z', + createdTS: 1713873440000, + creatorId: 'user-ghfld', + digitaloceancredentialConfig: {}, + id: `cattle-global-data:cc-${ cloudCredId }`, + labels: { 'cattle.io/creator': 'norman' }, + links: { + nodeTemplates: `https://localhost:8005/v3/nodeTemplates?cloudCredentialId=cattle-global-data%3Acc-${ cloudCredId }`, + remove: `https://localhost:8005/v3/cloudCredentials/cattle-global-data:cc-${ cloudCredId }`, + self: `https://localhost:8005/v3/cloudCredentials/cattle-global-data:cc-${ cloudCredId }`, + update: `https://localhost:8005/v3/cloudCredentials/cattle-global-data:cc-${ cloudCredId }` + }, + name: 'test-do-creds', + type: 'cloudCredential', + uuid: 'e6e0e54b-9077-46d7-8aa7-b9231a955aed' + }; +} +// /v1/rke-machine-config.cattle.io.digitaloceanconfigs/fleet-default/nc-${ provClusterId }-pool1-${machinePoolId}?* +export function generateFakeMachineConfigReply(provClusterId:string, machinePoolId:string):any { + return { + id: `fleet-default/nc-${ provClusterId }-pool1-${ machinePoolId }`, + type: 'rke-machine-config.cattle.io.digitaloceanconfig', + links: { + remove: `https://localhost:8005/v1/rke-machine-config.cattle.io.digitaloceanconfigs/fleet-default/nc-${ provClusterId }-pool1-${ machinePoolId }`, + self: `https://localhost:8005/v1/rke-machine-config.cattle.io.digitaloceanconfigs/fleet-default/nc-${ provClusterId }-pool1-${ machinePoolId }`, + update: `https://localhost:8005/v1/rke-machine-config.cattle.io.digitaloceanconfigs/fleet-default/nc-${ provClusterId }-pool1-${ machinePoolId }`, + view: `https://localhost:8005/apis/rke-machine-config.cattle.io/v1/namespaces/fleet-default/digitaloceanconfigs/nc-${ provClusterId }-pool1-${ machinePoolId }` + }, + accessToken: '', + apiVersion: 'rke-machine-config.cattle.io/v1', + backups: false, + image: 'ubuntu-20-04-x64', + ipv6: false, + kind: 'DigitaloceanConfig', + metadata: { + annotations: { + 'field.cattle.io/creatorId': 'user-ghfld', + ownerBindingsCreated: 'true' + }, + creationTimestamp: '2024-04-23T11:57:44Z', + fields: [ + `nc-${ provClusterId }-pool1-${ machinePoolId }`, + '27h' + ], + generateName: `nc-${ provClusterId }-pool1-`, + generation: 1, + name: `nc-${ provClusterId }-pool1-${ machinePoolId }`, + namespace: 'fleet-default', + ownerReferences: [ + { + apiVersion: 'provisioning.cattle.io/v1', + blockOwnerDeletion: true, + controller: true, + kind: 'Cluster', + name: provClusterId, + uid: 'fa5f2394-7a7c-4079-86e8-21b514792244' + } + ], + relationships: [ + { + fromId: `fleet-default/${ provClusterId }`, + fromType: 'provisioning.cattle.io.cluster', + rel: 'owner', + state: 'active', + message: 'Resource is Ready' + }, + { + toId: `fleet-default/nc-${ provClusterId }-pool1-${ machinePoolId }-digitaloceanconfigs-a`, + toType: 'rbac.authorization.k8s.io.role', + rel: 'owner', + state: 'active', + message: 'Resource is current' + }, + { + toId: `fleet-default/nc-${ provClusterId }-pool1-${ machinePoolId }-digitaloceanconfigs-a`, + toType: 'rbac.authorization.k8s.io.rolebinding', + rel: 'owner', + state: 'active', + message: 'Resource is current' + } + ], + resourceVersion: '141967', + state: { + error: false, + message: 'Resource is current', + name: 'active', + transitioning: false + }, + uid: '6a2d94e5-e6a6-4f5e-bede-2b21c3a2009e' + }, + monitoring: false, + privateNetworking: false, + region: 'lon1', + size: 's-4vcpu-8gb', + sshKeyContents: '', + sshKeyFingerprint: '', + sshPort: '22', + sshUser: 'root', + tags: '', + userdata: '' + }; +} + +export function generateFakeSecretsReply():any { + return [ + { + id: 'fleet-default/registryconfig-auth-reg1', + type: 'secret', + links: { + remove: 'https://localhost:8005/v1/secrets/fleet-default/registryconfig-auth-reg1', + self: 'https://localhost:8005/v1/secrets/fleet-default/registryconfig-auth-reg1', + update: 'https://localhost:8005/v1/secrets/fleet-default/registryconfig-auth-reg1', + view: 'https://localhost:8005/api/v1/namespaces/fleet-default/secrets/registryconfig-auth-reg1' + }, + _type: 'kubernetes.io/basic-auth', + apiVersion: 'v1', + data: { + password: 'YmJi', + username: 'YWFh' + }, + kind: 'Secret', + metadata: { + creationTimestamp: '2024-04-24T17:18:59Z', + fields: [ + 'registryconfig-auth-reg1', + 'kubernetes.io/basic-auth', + 2, + '9m31s' + ], + generateName: 'registryconfig-auth-', + name: 'registryconfig-auth-reg1', + namespace: 'fleet-default', + relationships: null, + resourceVersion: '526944', + state: { + error: false, + message: 'Resource is always ready', + name: 'active', + transitioning: false + }, + uid: '5634635f-9b3f-4872-9cc6-f9a3028bf306' + } + }, + { + id: 'fleet-default/registryconfig-auth-reg2', + type: 'secret', + links: { + remove: 'https://localhost:8005/v1/secrets/fleet-default/registryconfig-auth-reg2', + self: 'https://localhost:8005/v1/secrets/fleet-default/registryconfig-auth-reg2', + update: 'https://localhost:8005/v1/secrets/fleet-default/registryconfig-auth-reg2', + view: 'https://localhost:8005/api/v1/namespaces/fleet-default/secrets/registryconfig-auth-reg2' + }, + _type: 'kubernetes.io/basic-auth', + apiVersion: 'v1', + data: { + password: 'YmJi', + username: 'YWFh' + }, + kind: 'Secret', + metadata: { + creationTimestamp: '2024-04-24T17:18:59Z', + fields: [ + 'registryconfig-auth-reg2', + 'kubernetes.io/basic-auth', + 2, + '9m31s' + ], + generateName: 'registryconfig-auth-', + name: 'registryconfig-auth-reg2', + namespace: 'fleet-default', + relationships: null, + resourceVersion: '526944', + state: { + error: false, + message: 'Resource is always ready', + name: 'active', + transitioning: false + }, + uid: '5634635f-9b3f-4872-9cc6-f9a3028bf306' + } + } + ]; +} diff --git a/cypress/e2e/blueprints/nav/fake-cluster.ts b/cypress/e2e/blueprints/nav/fake-cluster.ts index bd343b9ecd1..a40e3dfa3df 100644 --- a/cypress/e2e/blueprints/nav/fake-cluster.ts +++ b/cypress/e2e/blueprints/nav/fake-cluster.ts @@ -6,6 +6,18 @@ import { generateFakePodSchema } from './k8s-schemas.ts'; +import { + generateFakeNodeDriversReply, + generateFakeCloudCredentialsReply, + generateFakeMachineConfigReply, + generateFakeCloudCredIndividualReply, + generateFakeSecretsReply +} from './edit-cluster.ts'; + +// GENERAL DATA NOT CONFIGURABLE, for now... +const MACHINE_POOL_ID = '995mj'; +const CLOUD_CRED_ID = 'srb7v'; + function generateProvClusterObj(provClusterId, mgmtClusterId) { return { id: `fleet-default/${ provClusterId }`, @@ -50,7 +62,7 @@ function generateProvClusterObj(provClusterId, mgmtClusterId) { message: 'Resource is current' }, { - toId: `fleet-default/nc-${ provClusterId }-pool1-48g2p`, + toId: `fleet-default/nc-${ provClusterId }-pool1-${ MACHINE_POOL_ID }`, toType: 'rke-machine-config.cattle.io.digitaloceanconfig', rel: 'owner', state: 'active', @@ -157,7 +169,7 @@ function generateProvClusterObj(provClusterId, mgmtClusterId) { uid: '326aa188-e66f-4cf0-8f54-9fc47e4c5d92' }, spec: { - cloudCredentialSecretName: 'cattle-global-data:cc-srb7v', + cloudCredentialSecretName: `cattle-global-data:cc-${ CLOUD_CRED_ID }`, kubernetesVersion: 'v1.27.10+rke2r1', localClusterAuthEndpoint: {}, rkeConfig: { @@ -180,7 +192,7 @@ function generateProvClusterObj(provClusterId, mgmtClusterId) { etcdRole: true, machineConfigRef: { kind: 'DigitaloceanConfig', - name: `nc-${ provClusterId }-pool1-48g2p` + name: `nc-${ provClusterId }-pool1-${ MACHINE_POOL_ID }` }, name: 'pool1', quantity: 1, @@ -191,7 +203,7 @@ function generateProvClusterObj(provClusterId, mgmtClusterId) { machineSelectorConfig: [ { config: { 'protect-kernel-defaults': false } } ], - registries: {}, + registries: { configs: { reg1: { authConfigSecretName: 'registryconfig-auth-reg1' }, reg2: { authConfigSecretName: 'registryconfig-auth-reg2' } } }, upgradeStrategy: { controlPlaneConcurrency: '1', controlPlaneDrainOptions: { @@ -2434,8 +2446,8 @@ function generateFakeDaemonsetsReply(mgmtClusterId) { ]; } -function generateFakeNavClusterData(provClusterId = 'some-prov-cluster-id', mgmtClusterId = 'some-mgmt-cluster-id'): any { - return { +function generateFakeNavClusterData(provClusterId = 'some-prov-cluster-id', mgmtClusterId = 'some-mgmt-cluster-id', addEditClusterCapabilities = false): any { + const fakeData = { provClusterObj: generateProvClusterObj(provClusterId, mgmtClusterId), mgmtClusterObj: generateMgmtClusterObj(provClusterId, mgmtClusterId), fakeNodeSchema: generateFakeNodeSchema(mgmtClusterId), @@ -2447,11 +2459,21 @@ function generateFakeNavClusterData(provClusterId = 'some-prov-cluster-id', mgmt fakeNamespacesReply: generateFakeNamespacesReply(mgmtClusterId), fakeDaemonsetsReply: generateFakeDaemonsetsReply(mgmtClusterId), }; + + if (addEditClusterCapabilities) { + fakeData.fakeNodeDriversReply = generateFakeNodeDriversReply(); + fakeData.fakeCloudCredentialsReply = generateFakeCloudCredentialsReply(CLOUD_CRED_ID); + fakeData.fakeMachineConfigReply = generateFakeMachineConfigReply(provClusterId, MACHINE_POOL_ID); + fakeData.fakeCloudCredIndividualReply = generateFakeCloudCredIndividualReply(CLOUD_CRED_ID); + fakeData.fakeSecretsReply = generateFakeSecretsReply(); + } + + return fakeData; } -export function generateFakeClusterDataAndIntercepts(fakeProvClusterId = 'some-prov-cluster-id', fakeMgmtClusterId = 'some-mgmt-cluster-id'): {} { +export function generateFakeClusterDataAndIntercepts(fakeProvClusterId = 'some-prov-cluster-id', fakeMgmtClusterId = 'some-mgmt-cluster-id', addEditClusterCapabilities = false): {} { const longClusterDescription = 'this-is-some-really-really-really-really-really-really-long-decription'; - const fakeNavClusterData = generateFakeNavClusterData(fakeProvClusterId, fakeMgmtClusterId); + const fakeNavClusterData = generateFakeNavClusterData(fakeProvClusterId, fakeMgmtClusterId, addEditClusterCapabilities); // add cluster to fleet clusters for testing https://github.com/rancher/dashboard/issues/9984 cy.intercept('GET', `/v1/fleet.cattle.io.clusters?*`, (req) => { @@ -2555,5 +2577,155 @@ export function generateFakeClusterDataAndIntercepts(fakeProvClusterId = 'some-p }); }).as('clusterPods'); + if (addEditClusterCapabilities) { + // intercept node drivers for fake cluster edit scenario + cy.intercept('GET', `/v1/management.cattle.io.nodedrivers?*`, (req) => { + req.reply({ + statusCode: 200, + body: { data: [fakeNavClusterData.fakeNodeDriversReply] }, + }); + }).as('nodeDrivers'); + + // intercept cloud credentials for fake cluster edit scenario + cy.intercept('GET', `/v3/cloudcredentials`, (req) => { + req.reply({ + statusCode: 200, + body: { data: [fakeNavClusterData.fakeCloudCredentialsReply] }, + }); + }).as('cloudCreds'); + + // intercept machine config for fake cluster edit scenario + cy.intercept('GET', `/v1/rke-machine-config.cattle.io.digitaloceanconfigs/fleet-default/nc-${ fakeProvClusterId }-pool1-${ MACHINE_POOL_ID }?*`, (req) => { + req.reply({ + statusCode: 200, + body: fakeNavClusterData.fakeMachineConfigReply, + }); + }).as('machineConfigDo'); + + // intercept individual cloud credential request + cy.intercept('GET', `/v3/cloudcredentials/cattle-global-data:cc-${ CLOUD_CRED_ID }`, (req) => { + req.reply({ + statusCode: 200, + body: fakeNavClusterData.fakeCloudCredIndividualReply, + }); + }).as('individualCloudCred'); + + // DIGITAL OCEAN REGIONS + cy.intercept('GET', `/meta/proxy/api.digitalocean.com/v2/regions?*`, (req) => { + req.reply({ + statusCode: 200, + body: { + meta: { total: 1 }, + regions: [ + { + name: 'London 1', + slug: 'lon1', + features: [ + 'backups', + 'ipv6', + 'metadata', + 'install_agent', + 'storage', + 'image_transfer' + ], + available: true, + sizes: [ + 's-1vcpu-1gb', + ] + } + ] + }, + }); + }).as('doRegions'); + + // DIGITAL OCEAN SIZES + cy.intercept('GET', `/meta/proxy/api.digitalocean.com/v2/sizes?*`, (req) => { + req.reply({ + statusCode: 200, + body: { + meta: { total: 1 }, + sizes: [ + { + slug: 's-1vcpu-1gb', + memory: 1024, + vcpus: 1, + disk: 25, + transfer: 1, + price_monthly: 6, + price_hourly: 0.00893, + regions: [ + 'ams3', + 'blr1', + 'fra1', + 'lon1', + 'nyc1', + 'nyc3', + 'sfo2', + 'sfo3', + 'sgp1', + 'syd1', + 'tor1' + ], + available: true, + description: 'Basic', + networking_througput: 2000 + } + ] + }, + }); + }).as('doSizes'); + + // DIGITAL OCEAN IMAGES + cy.intercept('GET', `/meta/proxy/api.digitalocean.com/v2/images?*`, (req) => { + req.reply({ + statusCode: 200, + body: { + meta: { total: 1 }, + images: [ + { + id: 129211873, + name: '20.04 (LTS) x64', + distribution: 'Ubuntu', + slug: 'ubuntu-20-04-x64', + public: true, + regions: [ + 'tor1', + 'syd1', + 'sgp1', + 'sfo3', + 'sfo2', + 'sfo1', + 'nyc3', + 'nyc2', + 'nyc1', + 'lon1', + 'fra1', + 'blr1', + 'ams3', + 'ams2' + ], + created_at: '2023-03-20T19:17:23Z', + min_disk_size: 7, + type: 'base', + size_gigabytes: 0.72, + description: 'Ubuntu 20.04 (LTS) x64', + tags: [], + status: 'available', + error_message: '' + } + ] + }, + }); + }).as('doImages'); + + // intercept secrets req (for registries in cluster) + cy.intercept('GET', `/v1/secrets?*`, (req) => { + req.reply({ + statusCode: 200, + body: { data: fakeNavClusterData.fakeSecretsReply }, + }); + }).as('secretsReply'); + } + return fakeNavClusterData; } diff --git a/cypress/e2e/po/edit/provisioning.cattle.io.cluster/edit/cluster-edit-generic.po.ts b/cypress/e2e/po/edit/provisioning.cattle.io.cluster/edit/cluster-edit-generic.po.ts index 15ea1b76d1a..d1972f7101c 100644 --- a/cypress/e2e/po/edit/provisioning.cattle.io.cluster/edit/cluster-edit-generic.po.ts +++ b/cypress/e2e/po/edit/provisioning.cattle.io.cluster/edit/cluster-edit-generic.po.ts @@ -1,4 +1,7 @@ import ClusterManagerCreateImportPagePo from '@/cypress/e2e/po/edit/provisioning.cattle.io.cluster/cluster-create-import.po'; +import TabbedPo from '@/cypress/e2e/po/components/tabbed.po'; +import ArrayListPo from '@/cypress/e2e/po/components/array-list.po'; +import LabeledSelectPo from '@/cypress/e2e/po/components/labeled-select.po'; /** * Covers core functionality that's common to the dashboard's edit cluster pages @@ -12,7 +15,19 @@ export default class ClusterManagerEditGenericPagePo extends ClusterManagerCreat return super.goTo(ClusterManagerEditGenericPagePo.createPath(clusterId, clusterName)); } - constructor(clusterId = '_', clusterName) { + constructor(clusterId = '_', clusterName: string) { super(ClusterManagerEditGenericPagePo.createPath(clusterId, clusterName)); } + + clickTab(selector: string) { + return new TabbedPo().clickTabWithSelector(selector); + } + + registryAuthenticationItems() { + return new ArrayListPo('[data-testid="registry-authentication"]'); + } + + registryAuthenticationField() { + return new LabeledSelectPo('[data-testid="registry-auth-select-or-create-0"]'); + } } diff --git a/cypress/e2e/tests/pages/manager/edit-fake-cluster.spec.ts b/cypress/e2e/tests/pages/manager/edit-fake-cluster.spec.ts new file mode 100644 index 00000000000..02a8a410e66 --- /dev/null +++ b/cypress/e2e/tests/pages/manager/edit-fake-cluster.spec.ts @@ -0,0 +1,42 @@ +import ClusterManagerListPagePo from '@/cypress/e2e/po/pages/cluster-manager/cluster-manager-list.po'; +import ClusterManagerEditGenericPagePo from '@/cypress/e2e/po/edit/provisioning.cattle.io.cluster/edit/cluster-edit-generic.po'; +import BurgerMenuPo from '@/cypress/e2e/po/side-bars/burger-side-menu.po'; +import HomePagePo from '@/cypress/e2e/po/pages/home.po'; + +import { generateFakeClusterDataAndIntercepts } from '@/cypress/e2e/blueprints/nav/fake-cluster'; +const fakeProvClusterId = 'some-fake-cluster-id'; +const fakeMgmtClusterId = 'some-fake-mgmt-id'; + +describe('Cluster Edit', { tags: ['@manager', '@adminUser'] }, () => { + describe('Cluster Edit (Fake DO cluster)', () => { + beforeEach(() => { + generateFakeClusterDataAndIntercepts(fakeProvClusterId, fakeMgmtClusterId, true); + + cy.login(); + }); + + it('Clearing a registry auth item on the UI (Cluster Edit Config) should retain its authentication ID', () => { + HomePagePo.goTo(); + const burgerMenu = new BurgerMenuPo(); + + BurgerMenuPo.toggle(); + const clusterManagementNavItem = burgerMenu.links().contains(`Cluster Management`); + + clusterManagementNavItem.should('exist'); + clusterManagementNavItem.click(); + const clusterList = new ClusterManagerListPagePo('_'); + + clusterList.waitForPage(); + clusterList.editCluster(fakeProvClusterId); + + const editCluster = new ClusterManagerEditGenericPagePo('_', fakeProvClusterId); + + editCluster.clickTab('#registry'); + editCluster.registryAuthenticationItems().closeArrayListItem(0); + + // registries is populated in fake-cluster -> "generateProvClusterObj" -> "spec.rkeConfig.registries" + // secrets need to be populated also, check fake-cluster -> INTERCEPT -> cy.intercept('GET', `/v1/secrets?*` ....) + editCluster.registryAuthenticationField().checkOptionSelected('registryconfig-auth-reg2 (HTTP Basic Auth: aaa)'); + }); + }); +}); diff --git a/shell/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryConfigs.vue b/shell/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryConfigs.vue index 559eb6f30c2..1bd3552c294 100644 --- a/shell/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryConfigs.vue +++ b/shell/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryConfigs.vue @@ -136,6 +136,7 @@ export default { :default-add-value="defaultAddValue" :initial-empty-row="true" :mode="mode" + data-testid="registry-authentication" @input="update" >