From 2587cd2413b305dd9c0eeedbf70a7b7abbf768cc Mon Sep 17 00:00:00 2001 From: manaswinidas Date: Thu, 4 Jul 2024 16:58:29 +0530 Subject: [PATCH] Handle only numbers workbench names --- .../tests/mocked/projects/workbench.cy.ts | 38 +++++++++++++++++++ frontend/src/api/k8s/notebooks.ts | 2 +- .../src/concepts/k8s/__tests__/utils.spec.ts | 1 + frontend/src/concepts/k8s/utils.ts | 16 +++++++- 4 files changed, 54 insertions(+), 3 deletions(-) diff --git a/frontend/src/__tests__/cypress/cypress/tests/mocked/projects/workbench.cy.ts b/frontend/src/__tests__/cypress/cypress/tests/mocked/projects/workbench.cy.ts index f43db7f18c..dc394967df 100644 --- a/frontend/src/__tests__/cypress/cypress/tests/mocked/projects/workbench.cy.ts +++ b/frontend/src/__tests__/cypress/cypress/tests/mocked/projects/workbench.cy.ts @@ -261,6 +261,44 @@ describe('Workbench page', () => { verifyRelativeURL('/projects/test-project?section=workbenches'); }); + it('Create workbench with numbers', () => { + initIntercepts({ isEmpty: true }); + workbenchPage.visit('test-project'); + workbenchPage.findCreateButton().click(); + createSpawnerPage.findSubmitButton().should('be.disabled'); + verifyRelativeURL('/projects/test-project/spawner'); + createSpawnerPage.findNameInput().fill('1234'); + createSpawnerPage.findDescriptionInput().fill('test-description'); + //to check scrollable dropdown selection + createSpawnerPage.findNotebookImage('test-9').click(); + createSpawnerPage.selectContainerSize( + 'XSmall Limits: 0.5 CPU, 500Mi Memory Requests: 0.1 CPU, 100Mi Memory', + ); + createSpawnerPage.findSubmitButton().should('be.enabled'); + + createSpawnerPage.findSubmitButton().click(); + + cy.wait('@createWorkbench').then((interception) => { + expect(interception.request.body).to.containSubset({ + metadata: { + labels: { + app: 'wb-1234', + 'opendatahub.io/dashboard': 'true', + 'opendatahub.io/odh-managed': 'true', + 'opendatahub.io/user': 'test-2duser', + }, + annotations: { + 'openshift.io/display-name': '1234', + 'openshift.io/description': 'test-description', + }, + name: 'wb-1234', + namespace: 'test-project', + }, + }); + }); + verifyRelativeURL('/projects/test-project?section=workbenches'); + }); + it('list workbench and table sorting', () => { initIntercepts({}); workbenchPage.visit('test-project'); diff --git a/frontend/src/api/k8s/notebooks.ts b/frontend/src/api/k8s/notebooks.ts index 85c496facf..56e1d2cd73 100644 --- a/frontend/src/api/k8s/notebooks.ts +++ b/frontend/src/api/k8s/notebooks.ts @@ -49,7 +49,7 @@ export const assembleNotebook = ( existingTolerations, existingResources, } = data; - const notebookId = overrideNotebookId || translateDisplayNameForK8s(notebookName); + const notebookId = overrideNotebookId || translateDisplayNameForK8s(notebookName, 'wb-'); const imageUrl = `${image.imageStream?.status?.dockerImageRepository}:${image.imageVersion?.name}`; const imageSelection = `${image.imageStream?.metadata.name}:${image.imageVersion?.name}`; diff --git a/frontend/src/concepts/k8s/__tests__/utils.spec.ts b/frontend/src/concepts/k8s/__tests__/utils.spec.ts index d4c288f028..713c699877 100644 --- a/frontend/src/concepts/k8s/__tests__/utils.spec.ts +++ b/frontend/src/concepts/k8s/__tests__/utils.spec.ts @@ -43,6 +43,7 @@ describe('translateDisplayNameForK8s', () => { expect(translateDisplayNameForK8s('$ymbols & Capitals and Spaces! (These are invalid!)')).toBe( 'ymbols--capitals-and-spaces-these-are-invalid', ); + expect(translateDisplayNameForK8s('1234', 'wb-')).toBe('wb-1234'); }); }); diff --git a/frontend/src/concepts/k8s/utils.ts b/frontend/src/concepts/k8s/utils.ts index ed4d410678..32df8aed7d 100644 --- a/frontend/src/concepts/k8s/utils.ts +++ b/frontend/src/concepts/k8s/utils.ts @@ -5,12 +5,24 @@ export const getDisplayNameFromK8sResource = (resource: K8sDSGResource): string export const getDescriptionFromK8sResource = (resource: K8sDSGResource): string => resource.metadata.annotations?.['openshift.io/description'] || ''; -export const translateDisplayNameForK8s = (name: string): string => - name +/** + * Converts a display name to a k8s safe variant, if needed a `safeK8sPrefix` can be provided to customize the prefix used to align with k8s standards if it is needed. + */ +export const translateDisplayNameForK8s = (name: string, safeK8sPrefix?: string): string => { + const translatedName: string = name .trim() .toLowerCase() .replace(/\s/g, '-') .replace(/[^A-Za-z0-9-]/g, ''); + if (safeK8sPrefix) { + if (/^\d+$/.test(translatedName)) { + const translatedNameWithoutNumbers = `wb-${translatedName}`; + return translatedNameWithoutNumbers; + } + } + return translatedName; +}; + export const isValidK8sName = (name?: string): boolean => name === undefined || (name.length > 0 && /^[a-z0-9]([-a-z0-9]*[a-z0-9])?$/.test(name));