From b663ff11da74f67090f6f62b8a1f2233c030749e Mon Sep 17 00:00:00 2001 From: ppadti Date: Fri, 10 Jan 2025 14:44:29 +0530 Subject: [PATCH] Add cypress tests to submit logic --- frontend/src/__mocks__/mockModelRegistry.ts | 74 +- .../cypress/pages/modelRegistrySettings.ts | 36 + .../cypress/cypress/support/commands/odh.ts | 6 +- .../modelRegistrySettings/mockCertificate.pem | 1 + .../modelRegistrySettings.cy.ts | 824 +++++++++++++++++- .../modelRegistrySettings/unSupportedFile.txt | 1 + .../CreateMRSecureDBSection.tsx | 18 +- .../modelRegistrySettings/CreateModal.tsx | 45 +- .../modelRegistrySettings/PemFileUpload.tsx | 3 + .../src/pages/modelRegistrySettings/utils.ts | 19 +- 10 files changed, 966 insertions(+), 61 deletions(-) create mode 100644 frontend/src/__tests__/cypress/cypress/tests/mocked/modelRegistrySettings/mockCertificate.pem create mode 100644 frontend/src/__tests__/cypress/cypress/tests/mocked/modelRegistrySettings/unSupportedFile.txt diff --git a/frontend/src/__mocks__/mockModelRegistry.ts b/frontend/src/__mocks__/mockModelRegistry.ts index d734162a3a..6b3f53d939 100644 --- a/frontend/src/__mocks__/mockModelRegistry.ts +++ b/frontend/src/__mocks__/mockModelRegistry.ts @@ -4,6 +4,8 @@ type MockModelRegistryType = { name?: string; namespace?: string; conditions?: K8sCondition[]; + sslRootCertificateConfigMap?: { name: string; key: string } | null; + sslRootCertificateSecret?: { name: string; key: string } | null; }; export const mockModelRegistry = ({ @@ -25,37 +27,47 @@ export const mockModelRegistry = ({ type: 'Available', }, ], -}: MockModelRegistryType): ModelRegistryKind => ({ - apiVersion: 'modelregistry.opendatahub.io/v1alpha1', - kind: 'ModelRegistry', - metadata: { - name, - creationTimestamp: '2024-03-14T08:01:42Z', - namespace, - }, - spec: { - grpc: {}, - rest: {}, - istio: { - gateway: { - grpc: { tls: {} }, - rest: { tls: {} }, - }, + sslRootCertificateConfigMap = null, + sslRootCertificateSecret = null, +}: MockModelRegistryType): ModelRegistryKind => { + const data: ModelRegistryKind = { + apiVersion: 'modelregistry.opendatahub.io/v1alpha1', + kind: 'ModelRegistry', + metadata: { + name, + creationTimestamp: '2024-03-14T08:01:42Z', + namespace, }, - postgres: { - database: 'model-registry', - host: 'model-registry-db', - passwordSecret: { - key: 'database-password', - name: 'model-registry-db', + spec: { + grpc: {}, + rest: {}, + istio: { + gateway: { + grpc: { tls: {} }, + rest: { tls: {} }, + }, + }, + mysql: { + database: 'model-registry', + host: 'model-registry-db', + passwordSecret: { + key: 'database-password', + name: 'model-registry-db', + }, + port: 5432, + skipDBCreation: false, + username: 'mlmduser', }, - port: 5432, - skipDBCreation: false, - sslMode: 'disable', - username: 'mlmduser', }, - }, - status: { - conditions, - }, -}); + status: { + conditions, + }, + }; + + if (sslRootCertificateConfigMap && data.spec.mysql) { + data.spec.mysql.sslRootCertificateConfigMap = sslRootCertificateConfigMap; + } else if (sslRootCertificateSecret && data.spec.mysql) { + data.spec.mysql.sslRootCertificateSecret = sslRootCertificateSecret; + } + return data; +}; diff --git a/frontend/src/__tests__/cypress/cypress/pages/modelRegistrySettings.ts b/frontend/src/__tests__/cypress/cypress/pages/modelRegistrySettings.ts index a4024eb399..efe7ea5f51 100644 --- a/frontend/src/__tests__/cypress/cypress/pages/modelRegistrySettings.ts +++ b/frontend/src/__tests__/cypress/cypress/pages/modelRegistrySettings.ts @@ -1,5 +1,7 @@ import { appChrome } from './appChrome'; +import { Contextual } from './components/Contextual'; import { K8sNameDescriptionField } from './components/subComponents/K8sNameDescriptionField'; +import { SearchSelector } from './components/subComponents/SearchSelector'; export enum FormFieldSelector { NAME = '#mr-name', @@ -29,6 +31,10 @@ export enum DatabaseDetailsTestId { class ModelRegistrySettings { k8sNameDescription = new K8sNameDescriptionField('mr'); + resourceNameSelect = new SearchSelector('existing-ca-resource-selector'); + + keySelect = new SearchSelector('existing-ca-key-selector'); + visit(wait = true) { cy.visitWithLogin('/modelRegistrySettings'); if (wait) { @@ -130,6 +136,10 @@ class ModelRegistrySettings { return cy.findByTestId('existing-ca-radio'); } + findUploadNewCertificateRadio() { + return cy.findByTestId('new-certificate-ca-radio'); + } + findAddSecureDbMRCheckbox() { return cy.findByTestId('add-secure-db-mr-checkbox'); } @@ -141,6 +151,32 @@ class ModelRegistrySettings { findExistingCAKeyInputToggle() { return cy.findByTestId('existing-ca-key-selector-toggle'); } + + getNewCertificateUpload() { + return new CertificateUpload(() => cy.findByTestId('certificate-upload')); + } + + findErrorFetchingResourceAlert() { + return cy.findByTestId('error-fetching-resource-alert'); + } + + findCertificateNote() { + return cy.findByTestId('certificate-note'); + } +} + +class CertificateUpload extends Contextual { + findUploadCertificateInput() { + return this.find().find('[data-testid="new-certificate-upload"] input[type="file"]'); + } + + uploadPemFile(filePath: string) { + this.findUploadCertificateInput().selectFile([filePath], { force: true }); + } + + findRestrictedFileUploadHelptext() { + return cy.findByTestId('restricted-file-example-helpText'); + } } export const modelRegistrySettings = new ModelRegistrySettings(); diff --git a/frontend/src/__tests__/cypress/cypress/support/commands/odh.ts b/frontend/src/__tests__/cypress/cypress/support/commands/odh.ts index 1da4c6a9f2..296dc1aab2 100644 --- a/frontend/src/__tests__/cypress/cypress/support/commands/odh.ts +++ b/frontend/src/__tests__/cypress/cypress/support/commands/odh.ts @@ -368,6 +368,10 @@ declare global { type: 'GET /api/modelRegistries', response: OdhResponse>, ) => Cypress.Chainable) & + (( + type: 'POST /api/modelRegistries', + response: OdhResponse, + ) => Cypress.Chainable) & (( type: 'PATCH /api/modelRegistries/:modelRegistryName', options: { @@ -656,7 +660,7 @@ declare global { ) => Cypress.Chainable) & (( type: 'GET /api/modelRegistryCertificates', - response: ListConfigSecretsResponse, + response: OdhResponse, ) => Cypress.Chainable) & (( type: 'POST /api/connection-types', diff --git a/frontend/src/__tests__/cypress/cypress/tests/mocked/modelRegistrySettings/mockCertificate.pem b/frontend/src/__tests__/cypress/cypress/tests/mocked/modelRegistrySettings/mockCertificate.pem new file mode 100644 index 0000000000..01f9fc9acf --- /dev/null +++ b/frontend/src/__tests__/cypress/cypress/tests/mocked/modelRegistrySettings/mockCertificate.pem @@ -0,0 +1 @@ +sample certificate \ No newline at end of file diff --git a/frontend/src/__tests__/cypress/cypress/tests/mocked/modelRegistrySettings/modelRegistrySettings.cy.ts b/frontend/src/__tests__/cypress/cypress/tests/mocked/modelRegistrySettings/modelRegistrySettings.cy.ts index 6bd6911495..049112cd94 100644 --- a/frontend/src/__tests__/cypress/cypress/tests/mocked/modelRegistrySettings/modelRegistrySettings.cy.ts +++ b/frontend/src/__tests__/cypress/cypress/tests/mocked/modelRegistrySettings/modelRegistrySettings.cy.ts @@ -28,18 +28,23 @@ const groupSubjects: RoleBindingSubject[] = [ }, ]; +const sampleCertificatePath = './cypress/tests/mocked/modelRegistrySettings/mockCertificate.pem'; +const unSupportedFilePath = './cypress/tests/mocked/modelRegistrySettings/unSupportedFile.txt'; + const setupMocksForMRSettingAccess = ({ hasModelRegistries = true, hasDatabasePassword = true, disableModelRegistrySecureDB = true, - secrets = [{ name: 'foo', keys: ['foo.crt', 'bar.crt'] }], + secrets = [{ name: 'sampleSecret', keys: ['foo.crt', 'bar.crt'] }], configMaps = [{ name: 'foo-bar', keys: ['bar.crt'] }], + failedToLoadCertificates = false, }: { hasModelRegistries?: boolean; hasDatabasePassword?: boolean; disableModelRegistrySecureDB?: boolean; secrets?: ConfigSecretItem[]; configMaps?: ConfigSecretItem[]; + failedToLoadCertificates?: boolean; }) => { asProductAdminUser(); cy.interceptOdh( @@ -64,6 +69,7 @@ const setupMocksForMRSettingAccess = ({ requiredCapabilities: [StackCapability.SERVICE_MESH, StackCapability.SERVICE_MESH_AUTHZ], }), ); + cy.interceptOdh('POST /api/modelRegistries', mockModelRegistry({})).as('createModelRegistry'); cy.interceptOdh( 'GET /api/modelRegistries', mockK8sResourceList( @@ -84,6 +90,25 @@ const setupMocksForMRSettingAccess = ({ }, ], }), + mockModelRegistry({ + name: 'test-registry-4', + sslRootCertificateConfigMap: { name: 'odh-trusted-ca-bundle', key: 'ca-bundle.crt' }, + }), + mockModelRegistry({ + name: 'test-registry-5', + sslRootCertificateConfigMap: { + name: 'odh-trusted-ca-bundle', + key: 'odh-ca-bundle.crt', + }, + }), + mockModelRegistry({ + name: 'test-registry-7', + sslRootCertificateSecret: { name: 'sampleSecret', key: 'foo.crt' }, + }), + mockModelRegistry({ + name: 'test-registry-8', + sslRootCertificateConfigMap: { name: 'new-certificate-db-credential', key: 'ca.crt' }, + }), ] : [], ), @@ -107,6 +132,59 @@ const setupMocksForMRSettingAccess = ({ req.reply(500); // Something went wrong on the backend when decoding the secret }, ); + cy.interceptOdh( + 'GET /api/modelRegistries/:modelRegistryName', + { + path: { modelRegistryName: 'test-registry-4' }, + }, + { + modelRegistry: mockModelRegistry({ + name: 'test-registry-4', + sslRootCertificateConfigMap: { name: 'odh-trusted-ca-bundle', key: 'ca-bundle.crt' }, + }), + databasePassword: hasDatabasePassword ? 'test-password' : undefined, + }, + ); + cy.interceptOdh( + 'GET /api/modelRegistries/:modelRegistryName', + { + path: { modelRegistryName: 'test-registry-5' }, + }, + { + modelRegistry: mockModelRegistry({ + name: 'test-registry-5', + sslRootCertificateConfigMap: { name: 'odh-trusted-ca-bundle', key: 'odh-ca-bundle.crt' }, + }), + databasePassword: hasDatabasePassword ? 'test-password' : undefined, + }, + ); + + cy.interceptOdh( + 'GET /api/modelRegistries/:modelRegistryName', + { + path: { modelRegistryName: 'test-registry-7' }, + }, + { + modelRegistry: mockModelRegistry({ + name: 'test-registry-7', + sslRootCertificateSecret: { name: 'sampleSecret', key: 'foo.crt' }, + }), + databasePassword: hasDatabasePassword ? 'test-password' : undefined, + }, + ); + cy.interceptOdh( + 'GET /api/modelRegistries/:modelRegistryName', + { + path: { modelRegistryName: 'test-registry-8' }, + }, + { + modelRegistry: mockModelRegistry({ + name: 'test-registry-8', + sslRootCertificateConfigMap: { name: 'new-certificate-db-credential', key: 'ca.crt' }, + }), + databasePassword: hasDatabasePassword ? 'test-password' : undefined, + }, + ); cy.interceptOdh( 'PATCH /api/modelRegistries/:modelRegistryName', @@ -117,7 +195,63 @@ const setupMocksForMRSettingAccess = ({ modelRegistry: mockModelRegistry({ name: 'test-registry-1' }), databasePassword: 'test-password', }, - ); + ).as('updateModelRegistry'); + + cy.interceptOdh( + 'PATCH /api/modelRegistries/:modelRegistryName', + { + path: { modelRegistryName: 'test-registry-4' }, + }, + { + modelRegistry: mockModelRegistry({ + name: 'test-registry-4', + sslRootCertificateConfigMap: { name: 'odh-trusted-ca-bundle', key: 'odh-ca-bundle.crt' }, + }), + databasePassword: 'test-password', + }, + ).as('updateTestRegistry-4'); + + cy.interceptOdh( + 'PATCH /api/modelRegistries/:modelRegistryName', + { + path: { modelRegistryName: 'test-registry-5' }, + }, + { + modelRegistry: mockModelRegistry({ + name: 'test-registry-5', + sslRootCertificateConfigMap: { name: 'foo-bar', key: 'bar.crt' }, + }), + databasePassword: 'test-password', + }, + ).as('updateTestRegistry-5'); + + cy.interceptOdh( + 'PATCH /api/modelRegistries/:modelRegistryName', + { + path: { modelRegistryName: 'test-registry-7' }, + }, + { + modelRegistry: mockModelRegistry({ + name: 'test-registry-7', + sslRootCertificateConfigMap: { name: 'foo-bar', key: 'bar.crt' }, + }), + databasePassword: 'test-password', + }, + ).as('updateTestRegistry-7'); + + cy.interceptOdh( + 'PATCH /api/modelRegistries/:modelRegistryName', + { + path: { modelRegistryName: 'test-registry-8' }, + }, + { + modelRegistry: mockModelRegistry({ + name: 'test-registry-8', + sslRootCertificateConfigMap: { name: 'foo-bar', key: 'bar.crt' }, + }), + databasePassword: 'test-password', + }, + ).as('updateTestRegistry-8'); cy.interceptOdh( 'GET /api/modelRegistryRoleBindings', @@ -136,12 +270,37 @@ const setupMocksForMRSettingAccess = ({ roleRefName: 'registry-user-test-registry-2', modelRegistryName: 'test-registry-2', }), + mockRoleBindingK8sResource({ + namespace: 'odh-model-registries', + name: 'test-registry-4-user', + subjects: groupSubjects, + roleRefName: 'registry-user-test-registry-4', + modelRegistryName: 'test-registry-4', + }), + mockRoleBindingK8sResource({ + namespace: 'odh-model-registries', + name: 'test-registry-8-user', + subjects: groupSubjects, + roleRefName: 'registry-user-test-registry-8', + modelRegistryName: 'test-registry-8', + }), + mockRoleBindingK8sResource({ + namespace: 'odh-model-registries', + name: 'test-registry-5-user', + subjects: groupSubjects, + roleRefName: 'registry-user-test-registry-5', + modelRegistryName: 'test-registry-5', + }), ]), ); cy.interceptOdh( 'GET /api/modelRegistryCertificates', - mockConfigMapsSecrets({ secrets, configMaps }), + failedToLoadCertificates + ? (req) => { + req.reply(500); // Something went wrong + } + : mockConfigMapsSecrets({ secrets, configMaps }), ); }; @@ -207,16 +366,91 @@ describe('CreateModal', () => { modelRegistrySettings.findSubmitButton().should('be.enabled'); modelRegistrySettings.shouldHaveNoErrors(); + modelRegistrySettings.findSubmitButton().click(); + + cy.wait('@createModelRegistry').then((interception) => { + expect(interception.request.body).to.containSubset({ + modelRegistry: { + metadata: { + name: 'image', + namespace: 'odh-model-registries', + annotations: { + 'openshift.io/description': '', + 'openshift.io/display-name': 'valid-mr-name', + }, + }, + spec: { + mysql: { + host: 'host', + port: 1234, + database: 'myDatabase', + username: 'validUser', + skipDBCreation: false, + }, + }, + }, + databasePassword: 'strongPassword', + }); + }); }); - it('checks whether the secure DB section exists and both first and second radio options are disabled', () => { - setupMocksForMRSettingAccess({ disableModelRegistrySecureDB: false }); + it('show error when certificates fails to load', () => { + setupMocksForMRSettingAccess({ + disableModelRegistrySecureDB: false, + failedToLoadCertificates: true, + }); modelRegistrySettings.visit(true); cy.findByText('Create model registry').click(); + modelRegistrySettings.findFormField(FormFieldSelector.NAME).type('valid-mr-name'); + modelRegistrySettings.findFormField(FormFieldSelector.HOST).type('host'); + modelRegistrySettings.findFormField(FormFieldSelector.PORT).type('1234'); + modelRegistrySettings.findFormField(FormFieldSelector.USERNAME).type('validUser'); + modelRegistrySettings.findFormField(FormFieldSelector.PASSWORD).type('strongPassword'); + modelRegistrySettings.findFormField(FormFieldSelector.DATABASE).type('myDatabase'); + modelRegistrySettings.findAddSecureDbMRCheckbox().should('exist'); + modelRegistrySettings.findAddSecureDbMRCheckbox().check(); + modelRegistrySettings.findErrorFetchingResourceAlert().should('exist'); + modelRegistrySettings + .findErrorFetchingResourceAlert() + .should('have.text', 'Danger alert:Error fetching config maps and secrets'); + modelRegistrySettings.findSubmitButton().should('be.disabled'); + }); + + it('checks whether the secure DB section exists, both first and second radio options are disabled and third option is checked', () => { + setupMocksForMRSettingAccess({ + disableModelRegistrySecureDB: false, + }); + modelRegistrySettings.visit(true); + cy.findByText('Create model registry').click(); + modelRegistrySettings.findAddSecureDbMRCheckbox().should('exist'); modelRegistrySettings.findAddSecureDbMRCheckbox().check(); modelRegistrySettings.findClusterWideCARadio().should('be.disabled'); modelRegistrySettings.findOpenshiftCARadio().should('be.disabled'); + modelRegistrySettings.findSubmitButton().should('be.disabled'); + modelRegistrySettings.findExistingCARadio().should('be.checked'); + }); + + it('when Use cluster-wide CA bundle is disabled, it should check Use Open Data Hub CA bundle', () => { + setupMocksForMRSettingAccess({ + disableModelRegistrySecureDB: false, + configMaps: [{ name: 'odh-trusted-ca-bundle', keys: ['odh-ca-bundle.crt'] }], + }); + modelRegistrySettings.visit(true); + cy.findByText('Create model registry').click(); + modelRegistrySettings.findFormField(FormFieldSelector.NAME).type('valid-mr-name'); + modelRegistrySettings.findFormField(FormFieldSelector.HOST).type('host'); + modelRegistrySettings.findFormField(FormFieldSelector.PORT).type('1234'); + modelRegistrySettings.findFormField(FormFieldSelector.USERNAME).type('validUser'); + modelRegistrySettings.findFormField(FormFieldSelector.PASSWORD).type('strongPassword'); + modelRegistrySettings.findFormField(FormFieldSelector.DATABASE).type('myDatabase'); + + modelRegistrySettings.findAddSecureDbMRCheckbox().should('exist'); + modelRegistrySettings.findAddSecureDbMRCheckbox().check(); + modelRegistrySettings.findClusterWideCARadio().should('be.disabled'); + modelRegistrySettings.findOpenshiftCARadio().should('be.enabled'); + modelRegistrySettings.findOpenshiftCARadio().should('be.checked'); + modelRegistrySettings.findSubmitButton().should('be.enabled'); }); it('both first and second radio options are enabled', () => { @@ -226,10 +460,300 @@ describe('CreateModal', () => { }); modelRegistrySettings.visit(true); cy.findByText('Create model registry').click(); + modelRegistrySettings.findFormField(FormFieldSelector.NAME).type('valid-mr-name'); + modelRegistrySettings.findFormField(FormFieldSelector.HOST).type('host'); + modelRegistrySettings.findFormField(FormFieldSelector.PORT).type('1234'); + modelRegistrySettings.findFormField(FormFieldSelector.USERNAME).type('validUser'); + modelRegistrySettings.findFormField(FormFieldSelector.PASSWORD).type('strongPassword'); + modelRegistrySettings.findFormField(FormFieldSelector.DATABASE).type('myDatabase'); + modelRegistrySettings.findAddSecureDbMRCheckbox().should('exist'); modelRegistrySettings.findAddSecureDbMRCheckbox().check(); modelRegistrySettings.findClusterWideCARadio().should('be.enabled'); + modelRegistrySettings.findClusterWideCARadio().should('be.checked'); + modelRegistrySettings.findOpenshiftCARadio().should('be.enabled'); + modelRegistrySettings.findSubmitButton().should('be.enabled'); + }); + + it('create a model registry with Use cluster-wide CA bundle option', () => { + setupMocksForMRSettingAccess({ + disableModelRegistrySecureDB: false, + configMaps: [{ name: 'odh-trusted-ca-bundle', keys: ['ca-bundle.crt'] }], + }); + modelRegistrySettings.visit(true); + cy.findByText('Create model registry').click(); + modelRegistrySettings.findFormField(FormFieldSelector.NAME).type('valid-mr-name'); + modelRegistrySettings.findFormField(FormFieldSelector.HOST).type('host'); + modelRegistrySettings.findFormField(FormFieldSelector.PORT).type('1234'); + modelRegistrySettings.findFormField(FormFieldSelector.USERNAME).type('validUser'); + modelRegistrySettings.findFormField(FormFieldSelector.PASSWORD).type('strongPassword'); + modelRegistrySettings.findFormField(FormFieldSelector.DATABASE).type('myDatabase'); + modelRegistrySettings.findAddSecureDbMRCheckbox().should('exist'); + modelRegistrySettings.findAddSecureDbMRCheckbox().check(); + modelRegistrySettings.findClusterWideCARadio().should('be.checked'); + modelRegistrySettings.findSubmitButton().should('be.enabled'); + modelRegistrySettings.findSubmitButton().click(); + + cy.wait('@createModelRegistry').then((interception) => { + expect(interception.request.body).to.containSubset({ + modelRegistry: { + metadata: { + name: 'valid-mr-name', + namespace: 'odh-model-registries', + annotations: { + 'openshift.io/description': '', + 'openshift.io/display-name': 'valid-mr-name', + }, + }, + spec: { + mysql: { + host: 'host', + port: 1234, + database: 'myDatabase', + username: 'validUser', + skipDBCreation: false, + sslRootCertificateConfigMap: { name: 'odh-trusted-ca-bundle', key: 'ca-bundle.crt' }, + }, + }, + }, + databasePassword: 'strongPassword', + }); + }); + }); + + it('create a model registry with Use Open Data Hub CA bundle option', () => { + setupMocksForMRSettingAccess({ + disableModelRegistrySecureDB: false, + configMaps: [{ name: 'odh-trusted-ca-bundle', keys: ['odh-ca-bundle.crt'] }], + }); + modelRegistrySettings.visit(true); + cy.findByText('Create model registry').click(); + modelRegistrySettings.findFormField(FormFieldSelector.NAME).type('valid-mr-name'); + modelRegistrySettings.findFormField(FormFieldSelector.HOST).type('host'); + modelRegistrySettings.findFormField(FormFieldSelector.PORT).type('1234'); + modelRegistrySettings.findFormField(FormFieldSelector.USERNAME).type('validUser'); + modelRegistrySettings.findFormField(FormFieldSelector.PASSWORD).type('strongPassword'); + modelRegistrySettings.findFormField(FormFieldSelector.DATABASE).type('myDatabase'); + modelRegistrySettings.findAddSecureDbMRCheckbox().should('exist'); + modelRegistrySettings.findAddSecureDbMRCheckbox().check(); + modelRegistrySettings.findClusterWideCARadio().should('be.disabled'); modelRegistrySettings.findOpenshiftCARadio().should('be.enabled'); + modelRegistrySettings.findOpenshiftCARadio().should('be.checked'); + modelRegistrySettings.findSubmitButton().should('be.enabled'); + modelRegistrySettings.findSubmitButton().click(); + + cy.wait('@createModelRegistry').then((interception) => { + expect(interception.request.body).to.containSubset({ + modelRegistry: { + metadata: { + name: 'valid-mr-name', + namespace: 'odh-model-registries', + annotations: { + 'openshift.io/description': '', + 'openshift.io/display-name': 'valid-mr-name', + }, + }, + spec: { + mysql: { + host: 'host', + port: 1234, + database: 'myDatabase', + username: 'validUser', + skipDBCreation: false, + sslRootCertificateConfigMap: { + name: 'odh-trusted-ca-bundle', + key: 'odh-ca-bundle.crt', + }, + }, + }, + }, + databasePassword: 'strongPassword', + }); + }); + }); + + it('create a model registry with Choose from existing certificates option - secret', () => { + setupMocksForMRSettingAccess({ + disableModelRegistrySecureDB: false, + }); + modelRegistrySettings.visit(true); + cy.findByText('Create model registry').click(); + modelRegistrySettings.findFormField(FormFieldSelector.NAME).type('valid-mr-name'); + modelRegistrySettings.findFormField(FormFieldSelector.HOST).type('host'); + modelRegistrySettings.findFormField(FormFieldSelector.PORT).type('1234'); + modelRegistrySettings.findFormField(FormFieldSelector.USERNAME).type('validUser'); + modelRegistrySettings.findFormField(FormFieldSelector.PASSWORD).type('strongPassword'); + modelRegistrySettings.findFormField(FormFieldSelector.DATABASE).type('myDatabase'); + modelRegistrySettings.findAddSecureDbMRCheckbox().should('exist'); + modelRegistrySettings.findAddSecureDbMRCheckbox().check(); + modelRegistrySettings.findClusterWideCARadio().should('be.disabled'); + modelRegistrySettings.findOpenshiftCARadio().should('be.disabled'); + modelRegistrySettings.findExistingCARadio().should('be.enabled'); + modelRegistrySettings.findExistingCARadio().should('be.checked'); + + modelRegistrySettings.findExistingCAKeyInputToggle().should('be.disabled'); + modelRegistrySettings.findExistingCAResourceInputToggle().should('be.enabled'); + modelRegistrySettings.resourceNameSelect.openAndSelectItem('sampleSecret', true); + modelRegistrySettings.findExistingCAKeyInputToggle().should('be.enabled'); + modelRegistrySettings.keySelect.openAndSelectItem('bar.crt', true); + + modelRegistrySettings.findSubmitButton().should('be.enabled'); + modelRegistrySettings.findSubmitButton().click(); + + cy.wait('@createModelRegistry').then((interception) => { + expect(interception.request.body).to.containSubset({ + modelRegistry: { + metadata: { + name: 'valid-mr-name', + namespace: 'odh-model-registries', + annotations: { + 'openshift.io/description': '', + 'openshift.io/display-name': 'valid-mr-name', + }, + }, + spec: { + mysql: { + host: 'host', + port: 1234, + database: 'myDatabase', + username: 'validUser', + skipDBCreation: false, + sslRootCertificateSecret: { name: 'sampleSecret', key: 'bar.crt' }, + }, + }, + }, + databasePassword: 'strongPassword', + }); + }); + }); + + it('create a model registry with Choose from existing certificates - config map', () => { + setupMocksForMRSettingAccess({ + disableModelRegistrySecureDB: false, + }); + modelRegistrySettings.visit(true); + cy.findByText('Create model registry').click(); + modelRegistrySettings.findFormField(FormFieldSelector.NAME).type('valid-mr-name'); + modelRegistrySettings.findFormField(FormFieldSelector.HOST).type('host'); + modelRegistrySettings.findFormField(FormFieldSelector.PORT).type('1234'); + modelRegistrySettings.findFormField(FormFieldSelector.USERNAME).type('validUser'); + modelRegistrySettings.findFormField(FormFieldSelector.PASSWORD).type('strongPassword'); + modelRegistrySettings.findFormField(FormFieldSelector.DATABASE).type('myDatabase'); + modelRegistrySettings.findAddSecureDbMRCheckbox().should('exist'); + modelRegistrySettings.findAddSecureDbMRCheckbox().check(); + modelRegistrySettings.findExistingCARadio().should('be.enabled'); + + modelRegistrySettings.findClusterWideCARadio().should('be.disabled'); + modelRegistrySettings.findOpenshiftCARadio().should('be.disabled'); + modelRegistrySettings.findExistingCARadio().should('be.checked'); + + modelRegistrySettings.findExistingCAKeyInputToggle().should('be.disabled'); + modelRegistrySettings.findExistingCAResourceInputToggle().should('be.enabled'); + modelRegistrySettings.resourceNameSelect.openAndSelectItem('foo-bar', true); + modelRegistrySettings.findExistingCAKeyInputToggle().should('be.enabled'); + modelRegistrySettings.keySelect.openAndSelectItem('bar.crt', true); + + modelRegistrySettings.findSubmitButton().should('be.enabled'); + modelRegistrySettings.findSubmitButton().click(); + + cy.wait('@createModelRegistry').then((interception) => { + expect(interception.request.body).to.containSubset({ + modelRegistry: { + metadata: { + name: 'valid-mr-name', + namespace: 'odh-model-registries', + annotations: { + 'openshift.io/description': '', + 'openshift.io/display-name': 'valid-mr-name', + }, + }, + spec: { + mysql: { + host: 'host', + port: 1234, + database: 'myDatabase', + username: 'validUser', + skipDBCreation: false, + sslRootCertificateConfigMap: { name: 'foo-bar', key: 'bar.crt' }, + }, + }, + }, + databasePassword: 'strongPassword', + }); + }); + }); + + it('create a model registry with Upload new certificate option', () => { + setupMocksForMRSettingAccess({ + disableModelRegistrySecureDB: false, + }); + modelRegistrySettings.visit(true); + cy.findByText('Create model registry').click(); + modelRegistrySettings.findFormField(FormFieldSelector.NAME).type('valid-mr-name'); + modelRegistrySettings.findFormField(FormFieldSelector.HOST).type('host'); + modelRegistrySettings.findFormField(FormFieldSelector.PORT).type('1234'); + modelRegistrySettings.findFormField(FormFieldSelector.USERNAME).type('validUser'); + modelRegistrySettings.findFormField(FormFieldSelector.PASSWORD).type('strongPassword'); + modelRegistrySettings.findFormField(FormFieldSelector.DATABASE).type('myDatabase'); + modelRegistrySettings.findAddSecureDbMRCheckbox().should('exist'); + modelRegistrySettings.findAddSecureDbMRCheckbox().check(); + modelRegistrySettings.findUploadNewCertificateRadio().check(); + const certificateUploadSection = modelRegistrySettings.getNewCertificateUpload(); + certificateUploadSection.uploadPemFile(sampleCertificatePath); + modelRegistrySettings.findSubmitButton().should('be.enabled'); + modelRegistrySettings.findSubmitButton().click(); + + cy.wait('@createModelRegistry').then((interception) => { + expect(interception.request.body).to.containSubset({ + modelRegistry: { + metadata: { + name: 'valid-mr-name', + namespace: 'odh-model-registries', + annotations: { + 'openshift.io/description': '', + 'openshift.io/display-name': 'valid-mr-name', + }, + }, + spec: { + mysql: { + host: 'host', + port: 1234, + database: 'myDatabase', + username: 'validUser', + skipDBCreation: false, + sslRootCertificateConfigMap: { name: 'valid-mr-name-db-credential', key: '' }, + }, + }, + }, + databasePassword: 'strongPassword', + newDatabaseCACertificate: 'sample certificate', + }); + }); + }); + + it('Show error when creating a model registry with Upload new certificate option with unsupported file', () => { + setupMocksForMRSettingAccess({ + disableModelRegistrySecureDB: false, + }); + modelRegistrySettings.visit(true); + cy.findByText('Create model registry').click(); + modelRegistrySettings.findFormField(FormFieldSelector.NAME).type('valid-mr-name'); + modelRegistrySettings.findFormField(FormFieldSelector.HOST).type('host'); + modelRegistrySettings.findFormField(FormFieldSelector.PORT).type('1234'); + modelRegistrySettings.findFormField(FormFieldSelector.USERNAME).type('validUser'); + modelRegistrySettings.findFormField(FormFieldSelector.PASSWORD).type('strongPassword'); + modelRegistrySettings.findFormField(FormFieldSelector.DATABASE).type('myDatabase'); + modelRegistrySettings.findAddSecureDbMRCheckbox().should('exist'); + modelRegistrySettings.findAddSecureDbMRCheckbox().check(); + modelRegistrySettings.findUploadNewCertificateRadio().check(); + modelRegistrySettings.findCertificateNote().should('exist'); + const certificateUploadSection = modelRegistrySettings.getNewCertificateUpload(); + certificateUploadSection.uploadPemFile(unSupportedFilePath); + certificateUploadSection.findRestrictedFileUploadHelptext().should('exist'); + certificateUploadSection + .findRestrictedFileUploadHelptext() + .should('have.text', 'Must be a PEM file: error status;'); + modelRegistrySettings.findSubmitButton().should('be.disabled'); }); }); @@ -270,6 +794,10 @@ describe('EditModelRegistry', () => { .should('have.value', 'model-registry'); modelRegistrySettings.findSubmitButton().should('be.enabled'); modelRegistrySettings.findSubmitButton().click(); + + cy.wait('@updateModelRegistry').then((interception) => { + expect(interception.request.body).to.containSubset({}); + }); }); it('Shows skeleton, when password is loading', () => { @@ -318,6 +846,292 @@ describe('EditModelRegistry', () => { .should('have.value', 'model-registry'); modelRegistrySettings.findSubmitButton().should('be.disabled'); }); + + it('Edit model registry(without CA certificate) to add CA certificate with Use cluster-wide CA bundle option', () => { + setupMocksForMRSettingAccess({ + disableModelRegistrySecureDB: false, + configMaps: [{ name: 'odh-trusted-ca-bundle', keys: ['ca-bundle.crt'] }], + }); + modelRegistrySettings.visit(true); + modelRegistrySettings + .findModelRegistryRow('test-registry-1') + .findKebabAction('Edit model registry') + .click(); + modelRegistrySettings.findAddSecureDbMRCheckbox().should('exist'); + modelRegistrySettings.findAddSecureDbMRCheckbox().should('not.be.checked'); + modelRegistrySettings.findAddSecureDbMRCheckbox().check(); + + modelRegistrySettings.findSubmitButton().should('be.enabled'); + modelRegistrySettings.findSubmitButton().click(); + + cy.wait('@updateModelRegistry').then((interception) => { + expect(interception.request.body).to.containSubset({ + modelRegistry: { + metadata: { + annotations: { + 'openshift.io/description': '', + 'openshift.io/display-name': 'test-registry-1', + }, + }, + spec: { + mysql: { + host: 'model-registry-db', + port: 5432, + database: 'model-registry', + username: 'mlmduser', + sslRootCertificateConfigMap: { name: 'odh-trusted-ca-bundle', key: 'ca-bundle.crt' }, + sslRootCertificateSecret: null, + }, + }, + }, + databasePassword: 'test-password', + }); + }); + }); + + it('Edit model registry with Use cluster-wide CA bundle option selected to add CA certificate with Open Data Hub CA bundle option', () => { + setupMocksForMRSettingAccess({ + disableModelRegistrySecureDB: false, + configMaps: [{ name: 'odh-trusted-ca-bundle', keys: ['ca-bundle.crt', 'odh-ca-bundle.crt'] }], + }); + modelRegistrySettings.visit(true); + modelRegistrySettings + .findModelRegistryRow('test-registry-4') + .findKebabAction('Edit model registry') + .click(); + modelRegistrySettings.findAddSecureDbMRCheckbox().should('be.checked'); + modelRegistrySettings.findClusterWideCARadio().should('be.checked'); + modelRegistrySettings.findSubmitButton().should('be.enabled'); + + modelRegistrySettings.findOpenshiftCARadio().should('be.enabled'); + modelRegistrySettings.findOpenshiftCARadio().check(); + + modelRegistrySettings.findSubmitButton().should('be.enabled'); + modelRegistrySettings.findSubmitButton().click(); + + cy.wait('@updateTestRegistry-4').then((interception) => { + expect(interception.request.body).to.containSubset({ + modelRegistry: { + metadata: { + annotations: { + 'openshift.io/description': '', + 'openshift.io/display-name': 'test-registry-4', + }, + }, + spec: { + mysql: { + host: 'model-registry-db', + port: 5432, + database: 'model-registry', + username: 'mlmduser', + sslRootCertificateConfigMap: { + name: 'odh-trusted-ca-bundle', + key: 'odh-ca-bundle.crt', + }, + sslRootCertificateSecret: null, + }, + }, + }, + databasePassword: 'test-password', + }); + }); + }); + + it('Edit model registry with Open Data Hub CA bundle option selected to add CA certificate with Choose from existing certificates option - secret', () => { + setupMocksForMRSettingAccess({ + disableModelRegistrySecureDB: false, + configMaps: [{ name: 'odh-trusted-ca-bundle', keys: ['odh-ca-bundle.crt'] }], + secrets: [{ name: 'sampleSecret', keys: ['bar.crt'] }], + }); + modelRegistrySettings.visit(true); + modelRegistrySettings + .findModelRegistryRow('test-registry-5') + .findKebabAction('Edit model registry') + .click(); + modelRegistrySettings.findAddSecureDbMRCheckbox().should('be.checked'); + modelRegistrySettings.findOpenshiftCARadio().should('be.checked'); + modelRegistrySettings.findSubmitButton().should('be.enabled'); + + modelRegistrySettings.findExistingCARadio().should('be.enabled'); + modelRegistrySettings.findExistingCARadio().click(); + + modelRegistrySettings.findExistingCAKeyInputToggle().should('be.disabled'); + modelRegistrySettings.findExistingCAResourceInputToggle().should('be.enabled'); + modelRegistrySettings.resourceNameSelect.openAndSelectItem('sampleSecret', true); + modelRegistrySettings.findExistingCAKeyInputToggle().should('be.enabled'); + modelRegistrySettings.keySelect.openAndSelectItem('bar.crt', true); + + modelRegistrySettings.findSubmitButton().should('be.enabled'); + modelRegistrySettings.findSubmitButton().click(); + + cy.wait('@updateTestRegistry-5').then((interception) => { + expect(interception.request.body).to.containSubset({ + modelRegistry: { + metadata: { + annotations: { + 'openshift.io/description': '', + 'openshift.io/display-name': 'test-registry-5', + }, + }, + spec: { + mysql: { + host: 'model-registry-db', + port: 5432, + database: 'model-registry', + username: 'mlmduser', + sslRootCertificateSecret: { name: 'sampleSecret', key: 'bar.crt' }, + sslRootCertificateConfigMap: null, + }, + }, + }, + databasePassword: 'test-password', + }); + }); + }); + + it('Edit model registry with Secrets selected to add CA certificate with Choose from existing certificates option - secret', () => { + setupMocksForMRSettingAccess({ + disableModelRegistrySecureDB: false, + secrets: [ + { name: 'sampleSecret', keys: ['foo.crt'] }, + { name: 'new-secret', keys: ['ca.crt'] }, + ], + }); + modelRegistrySettings.visit(true); + modelRegistrySettings + .findModelRegistryRow('test-registry-7') + .findKebabAction('Edit model registry') + .click(); + modelRegistrySettings.findAddSecureDbMRCheckbox().should('be.checked'); + + modelRegistrySettings.findSubmitButton().should('be.enabled'); + + modelRegistrySettings.resourceNameSelect.openAndSelectItem('new-secret', true); + modelRegistrySettings.keySelect.openAndSelectItem('ca.crt', true); + + modelRegistrySettings.findSubmitButton().should('be.enabled'); + modelRegistrySettings.findSubmitButton().click(); + + cy.wait('@updateTestRegistry-7').then((interception) => { + expect(interception.request.body).to.containSubset({ + modelRegistry: { + metadata: { + annotations: { + 'openshift.io/description': '', + 'openshift.io/display-name': 'test-registry-7', + }, + }, + spec: { + mysql: { + host: 'model-registry-db', + port: 5432, + database: 'model-registry', + username: 'mlmduser', + sslRootCertificateConfigMap: null, + sslRootCertificateSecret: { name: 'new-secret', key: 'ca.crt' }, + }, + }, + }, + databasePassword: 'test-password', + }); + }); + }); + + it('Edit model registry with Upload new certificate option selected to add CA certificate with Choose from existing certificates option - config map', () => { + setupMocksForMRSettingAccess({ + disableModelRegistrySecureDB: false, + configMaps: [ + { name: 'foo-bar', keys: ['bar.crt'] }, + { name: 'new-certificate-db-credentilas', keys: ['ca.crt'] }, + ], + }); + modelRegistrySettings.visit(true); + modelRegistrySettings + .findModelRegistryRow('test-registry-8') + .findKebabAction('Edit model registry') + .click(); + modelRegistrySettings.findAddSecureDbMRCheckbox().should('be.checked'); + + // checking the MR form should naturally change to show that they are using "Choose from existing certificates" with the right configmap/key selected + modelRegistrySettings.findExistingCARadio().should('be.checked'); + modelRegistrySettings.findSubmitButton().should('be.enabled'); + + modelRegistrySettings.resourceNameSelect.openAndSelectItem('foo-bar', true); + modelRegistrySettings.keySelect.openAndSelectItem('bar.crt', true); + + modelRegistrySettings.findSubmitButton().should('be.enabled'); + modelRegistrySettings.findSubmitButton().click(); + + cy.wait('@updateTestRegistry-8').then((interception) => { + expect(interception.request.body).to.containSubset({ + modelRegistry: { + metadata: { + annotations: { + 'openshift.io/description': '', + 'openshift.io/display-name': 'test-registry-8', + }, + }, + spec: { + mysql: { + host: 'model-registry-db', + port: 5432, + database: 'model-registry', + username: 'mlmduser', + sslRootCertificateConfigMap: { name: 'foo-bar', key: 'bar.crt' }, + sslRootCertificateSecret: null, + }, + }, + }, + databasePassword: 'test-password', + }); + }); + }); + + it('Edit model registry with Upload new certificate option selected to add CA certificate with Choose from existing certificates option - secret', () => { + setupMocksForMRSettingAccess({ + disableModelRegistrySecureDB: false, + }); + modelRegistrySettings.visit(true); + modelRegistrySettings + .findModelRegistryRow('test-registry-8') + .findKebabAction('Edit model registry') + .click(); + modelRegistrySettings.findAddSecureDbMRCheckbox().should('be.checked'); + + // checking the MR form should naturally change to show that they are using "Choose from existing certificates" with the right configmap/key selected + modelRegistrySettings.findExistingCARadio().should('be.checked'); + modelRegistrySettings.findSubmitButton().should('be.enabled'); + + modelRegistrySettings.resourceNameSelect.openAndSelectItem('sampleSecret', true); + modelRegistrySettings.keySelect.openAndSelectItem('foo.crt', true); + + modelRegistrySettings.findSubmitButton().should('be.enabled'); + modelRegistrySettings.findSubmitButton().click(); + + cy.wait('@updateTestRegistry-8').then((interception) => { + expect(interception.request.body).to.containSubset({ + modelRegistry: { + metadata: { + annotations: { + 'openshift.io/description': '', + 'openshift.io/display-name': 'test-registry-8', + }, + }, + spec: { + mysql: { + host: 'model-registry-db', + port: 5432, + database: 'model-registry', + username: 'mlmduser', + sslRootCertificateSecret: { name: 'sampleSecret', key: 'foo.crt' }, + sslRootCertificateConfigMap: null, + }, + }, + }, + databasePassword: 'test-password', + }); + }); + }); }); describe('ManagePermissions', () => { diff --git a/frontend/src/__tests__/cypress/cypress/tests/mocked/modelRegistrySettings/unSupportedFile.txt b/frontend/src/__tests__/cypress/cypress/tests/mocked/modelRegistrySettings/unSupportedFile.txt new file mode 100644 index 0000000000..8773f39855 --- /dev/null +++ b/frontend/src/__tests__/cypress/cypress/tests/mocked/modelRegistrySettings/unSupportedFile.txt @@ -0,0 +1 @@ +file content \ No newline at end of file diff --git a/frontend/src/pages/modelRegistrySettings/CreateMRSecureDBSection.tsx b/frontend/src/pages/modelRegistrySettings/CreateMRSecureDBSection.tsx index da3068115c..6869ce2824 100644 --- a/frontend/src/pages/modelRegistrySettings/CreateMRSecureDBSection.tsx +++ b/frontend/src/pages/modelRegistrySettings/CreateMRSecureDBSection.tsx @@ -12,6 +12,7 @@ import { ResourceType, SecureDBRType, } from './const'; +import { isClusterWideCABundleEnabled, isOpenshiftCAbundleEnabled } from './utils'; export interface SecureDBInfo { type: SecureDBRType; @@ -71,18 +72,8 @@ export const CreateMRSecureDBSection: React.FC = ( return false; }; - const clusterWideCABundle = existingCertConfigMaps.find( - (configMap) => configMap.name === ODH_TRUSTED_BUNDLE && configMap.keys.includes(CA_BUNDLE_CRT), - ); - - const isClusterWideCABundleAvailable = !!clusterWideCABundle; - - const openshiftCAbundle = existingCertConfigMaps.find( - (configMap) => - configMap.name === ODH_TRUSTED_BUNDLE && configMap.keys.includes(ODH_CA_BUNDLE_CRT), - ); - - const isProductCABundleAvailable = !!openshiftCAbundle; + const isClusterWideCABundleAvailable = isClusterWideCABundleEnabled(existingCertConfigMaps); + const isProductCABundleAvailable = isOpenshiftCAbundleEnabled(existingCertConfigMaps); const getKeysByName = (configMapsSecrets: ConfigSecretItem[], targetName: string): string[] => { const configMapSecret = configMapsSecrets.find( @@ -306,6 +297,7 @@ export const CreateMRSecureDBSection: React.FC = ( handleSecureDBTypeChange(SecureDBRType.NEW)} label="Upload new certificate" id="new-ca" @@ -316,6 +308,7 @@ export const CreateMRSecureDBSection: React.FC = ( isInline title="Note" variant="info" + data-testid="certificate-note" style={{ marginLeft: 'var(--pf-t--global--spacer--lg)' }} > Uploading a certificate below creates the {newConfigMapName} ConfigMap @@ -324,6 +317,7 @@ export const CreateMRSecureDBSection: React.FC = ( diff --git a/frontend/src/pages/modelRegistrySettings/CreateModal.tsx b/frontend/src/pages/modelRegistrySettings/CreateModal.tsx index cf4c1aab50..2e1769accc 100644 --- a/frontend/src/pages/modelRegistrySettings/CreateModal.tsx +++ b/frontend/src/pages/modelRegistrySettings/CreateModal.tsx @@ -31,6 +31,8 @@ import { findConfigMap, findSecureDBType, constructRequestBody, + isClusterWideCABundleEnabled, + isOpenshiftCAbundleEnabled, } from '~/pages/modelRegistrySettings/utils'; import { RecursivePartial } from '~/typeHelpers'; import { CreateMRSecureDBSection, SecureDBInfo } from './CreateMRSecureDBSection'; @@ -55,14 +57,6 @@ const CreateModal: React.FC = ({ onClose, refresh, modelRegist const [password, setPassword] = React.useState(''); const [database, setDatabase] = React.useState(''); const [addSecureDB, setAddSecureDB] = React.useState(false); - const [secureDBInfo, setSecureDBInfo] = React.useState({ - type: SecureDBRType.CLUSTER_WIDE, - nameSpace: '', - resourceName: '', - certificate: '', - key: '', - isValid: true, - }); const [isHostTouched, setIsHostTouched] = React.useState(false); const [isPortTouched, setIsPortTouched] = React.useState(false); const [isUsernameTouched, setIsUsernameTouched] = React.useState(false); @@ -74,9 +68,33 @@ const CreateModal: React.FC = ({ onClose, refresh, modelRegist const [configSecrets, configSecretsLoaded, configSecretsError] = useModelRegistryCertificateNames( !addSecureDB, ); - + const [secureDBInfo, setSecureDBInfo] = React.useState({ + type: SecureDBRType.CLUSTER_WIDE, + nameSpace: '', + resourceName: '', + certificate: '', + key: '', + isValid: true, + }); const modelRegistryNamespace = dscStatus?.components?.modelregistry?.registriesNamespace || ''; + React.useEffect(() => { + if (configSecretsLoaded && !configSecretsError && !mr) { + setSecureDBInfo((prev) => ({ + ...prev, + type: isClusterWideCABundleEnabled(configSecrets.configMaps) + ? SecureDBRType.CLUSTER_WIDE + : isOpenshiftCAbundleEnabled(configSecrets.configMaps) + ? SecureDBRType.OPENSHIFT + : SecureDBRType.EXISTING, + isValid: !!( + isClusterWideCABundleEnabled(configSecrets.configMaps) || + isOpenshiftCAbundleEnabled(configSecrets.configMaps) + ), + })); + } + }, [configSecretsLoaded, configSecrets.configMaps, mr, configSecretsError]); + React.useEffect(() => { if (mr) { const dbSpec = mr.spec.mysql || mr.spec.postgres; @@ -227,7 +245,7 @@ const CreateModal: React.FC = ({ onClose, refresh, modelRegist hasContent(port) && hasContent(username) && hasContent(database) && - (!addSecureDB || secureDBInfo.isValid); + (!addSecureDB || (secureDBInfo.isValid && !configSecretsError)); return ( = ({ onClose, refresh, modelRegist setSecureDBInfo={setSecureDBInfo} /> ) : ( - + {configSecretsError?.message} ))} diff --git a/frontend/src/pages/modelRegistrySettings/PemFileUpload.tsx b/frontend/src/pages/modelRegistrySettings/PemFileUpload.tsx index 85a1c2df5f..5684a6daee 100644 --- a/frontend/src/pages/modelRegistrySettings/PemFileUpload.tsx +++ b/frontend/src/pages/modelRegistrySettings/PemFileUpload.tsx @@ -49,7 +49,9 @@ export const PemFileUpload: React.FC<{ onChange: (value: string) => void }> = ({ <> void }> = ({ {isRejected ? 'Must be a PEM file' : 'Upload a PEM file'} diff --git a/frontend/src/pages/modelRegistrySettings/utils.ts b/frontend/src/pages/modelRegistrySettings/utils.ts index e268a1e686..a06b2517a9 100644 --- a/frontend/src/pages/modelRegistrySettings/utils.ts +++ b/frontend/src/pages/modelRegistrySettings/utils.ts @@ -1,5 +1,5 @@ import { RecursivePartial } from '~/typeHelpers'; -import { ModelRegistryKind } from '~/k8sTypes'; +import { ConfigSecretItem, ModelRegistryKind } from '~/k8sTypes'; import { CA_BUNDLE_CRT, ODH_CA_BUNDLE_CRT, @@ -51,3 +51,20 @@ export const constructRequestBody = ( return mr; }; + +export const isClusterWideCABundleEnabled = ( + existingCertConfigMaps: ConfigSecretItem[], +): boolean => { + const clusterWideCABundle = existingCertConfigMaps.find( + (configMap) => configMap.name === ODH_TRUSTED_BUNDLE && configMap.keys.includes(CA_BUNDLE_CRT), + ); + return !!clusterWideCABundle; +}; + +export const isOpenshiftCAbundleEnabled = (existingCertConfigMaps: ConfigSecretItem[]): boolean => { + const openshiftCAbundle = existingCertConfigMaps.find( + (configMap) => + configMap.name === ODH_TRUSTED_BUNDLE && configMap.keys.includes(ODH_CA_BUNDLE_CRT), + ); + return !!openshiftCAbundle; +};