diff --git a/packages/manager/.changeset/pr-11371-changed-1733409504298.md b/packages/manager/.changeset/pr-11371-changed-1733409504298.md new file mode 100644 index 00000000000..cbdaacb1fc5 --- /dev/null +++ b/packages/manager/.changeset/pr-11371-changed-1733409504298.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Changed +--- + +DBaaS : Updated copy, placeholders, and button text in Access Controls, fixed default DB value for legacy instances ([#11371](https://github.com/linode/manager/pull/11371)) diff --git a/packages/manager/cypress/e2e/core/databases/update-database.spec.ts b/packages/manager/cypress/e2e/core/databases/update-database.spec.ts index 9c05905c5c3..44167766719 100644 --- a/packages/manager/cypress/e2e/core/databases/update-database.spec.ts +++ b/packages/manager/cypress/e2e/core/databases/update-database.spec.ts @@ -97,14 +97,17 @@ const manageAccessControl = (allowedIps: string[], existingIps: number = 0) => { cy.findByTestId('button-access-control').click(); ui.drawer - .findByTitle('Manage Access Controls') + .findByTitle('Manage Access') .should('be.visible') .within(() => { allowedIps.forEach((allowedIp, index) => { - ui.button.findByTitle('Add an IP').click(); - + if (existingIps > 0) { + ui.button.findByTitle('Add Another IP').click(); + } else { + ui.button.findByTitle('Add an IP').click(); + } cy.findByLabelText( - `Allowed IP Address(es) or Range(s) ip-address-${index + existingIps}` + `Allowed IP Addresses or Ranges ip-address-${index + existingIps}` ) .click() .type(allowedIp); @@ -371,7 +374,7 @@ describe('Update database clusters', () => { manageAccessControl([randomIp()], 1); cy.wait('@updateDatabase'); - ui.drawer.findByTitle('Manage Access Controls').within(() => { + ui.drawer.findByTitle('Manage Access').within(() => { cy.findByText(errorMessage).should('be.visible'); ui.drawerCloseButton.find().click(); }); diff --git a/packages/manager/src/features/Databases/DatabaseCreate/DatabaseCreateAccessControls.test.tsx b/packages/manager/src/features/Databases/DatabaseCreate/DatabaseCreateAccessControls.test.tsx index 879986492c9..b09418b4dd5 100644 --- a/packages/manager/src/features/Databases/DatabaseCreate/DatabaseCreateAccessControls.test.tsx +++ b/packages/manager/src/features/Databases/DatabaseCreate/DatabaseCreateAccessControls.test.tsx @@ -25,7 +25,7 @@ describe('DatabaseCreateAccessControls', () => { /> ); - expect(getAllByText('Add Access Controls')).toHaveLength(1); + expect(getAllByText('Manage Access')).toHaveLength(1); expect(getAllByTestId('domain-transfer-input')).toHaveLength(1); expect(getAllByTestId('button')).toHaveLength(1); @@ -60,7 +60,7 @@ describe('DatabaseCreateAccessControls', () => { /> ); - expect(getAllByText('Add Access Controls')).toHaveLength(1); + expect(getAllByText('Manage Access')).toHaveLength(1); expect(getAllByTestId('domain-transfer-input')).toHaveLength(3); expect(getAllByTestId('button')).toHaveLength(3); @@ -91,7 +91,7 @@ describe('DatabaseCreateAccessControls', () => { /> ); - expect(getAllByText('Add Access Controls')).toHaveLength(1); + expect(getAllByText('Manage Access')).toHaveLength(1); expect(getAllByTestId('domain-transfer-input')).toHaveLength(1); expect(getAllByTestId('button')).toHaveLength(1); diff --git a/packages/manager/src/features/Databases/DatabaseCreate/DatabaseCreateAccessControls.tsx b/packages/manager/src/features/Databases/DatabaseCreate/DatabaseCreateAccessControls.tsx index 3b9d422307b..63cbf139023 100644 --- a/packages/manager/src/features/Databases/DatabaseCreate/DatabaseCreateAccessControls.tsx +++ b/packages/manager/src/features/Databases/DatabaseCreate/DatabaseCreateAccessControls.tsx @@ -12,7 +12,10 @@ import { makeStyles } from 'tss-react/mui'; import { Link } from 'src/components/Link'; import { MultipleIPInput } from 'src/components/MultipleIPInput/MultipleIPInput'; -import { ipFieldPlaceholder } from 'src/utilities/ipUtils'; +import { + ipFieldPlaceholder, + ipV6FieldPlaceholder, +} from 'src/utilities/ipUtils'; import { useIsDatabasesEnabled } from '../utilities'; @@ -63,14 +66,14 @@ export const DatabaseCreateAccessControls = (props: Props) => { return ( - Add Access Controls + Manage Access {isDatabasesV2GA ? ( <> - Add IPv4 addresses or ranges that should be authorized to access - this cluster. - + Add IPv6 (recommended) or IPv4 addresses or ranges that should be + authorized to access this cluster.{' '} + Learn more . @@ -123,13 +126,14 @@ export const DatabaseCreateAccessControls = (props: Props) => { value="specific" /> 1 ? 'Add Another IP' : 'Add an IP'} className={classes.multipleIPInput} disabled={accessOption === 'none' || disabled} ips={ips} onBlur={onBlur} onChange={onChange} - placeholder={ipFieldPlaceholder} - title="Allowed IP Address(es) or Range(s)" + placeholder={ipV6FieldPlaceholder} + title="Allowed IP Addresses or Ranges" /> } diff --git a/packages/manager/src/features/Databases/DatabaseDetail/AddAccessControlDrawer.test.tsx b/packages/manager/src/features/Databases/DatabaseDetail/AddAccessControlDrawer.test.tsx index e0a9abac2b5..12118fd1433 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/AddAccessControlDrawer.test.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/AddAccessControlDrawer.test.tsx @@ -1,4 +1,5 @@ import { fireEvent, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; import * as React from 'react'; import { databaseFactory } from 'src/factories'; @@ -46,7 +47,7 @@ describe('Add Access Controls drawer', () => { await screen.findByDisplayValue(IPv4ListWithMasks[2]); }); - it('Should have a disabled Add Inbound Sources button until an inbound source field is touched', () => { + it('Should have a disabled Add Inbound Sources button until an inbound source field is touched', async () => { const db = { allow_list: IPv4List, engine: 'postgresql', @@ -63,8 +64,8 @@ describe('Add Access Controls drawer', () => { // Before making a change to the IP addresses, the "Add Inbound Sources" button should be disabled. expect(addAccessControlsButton).toHaveAttribute('aria-disabled', 'true'); - const addAnIPButton = getByText('Add an IP'); - fireEvent.click(addAnIPButton); + const addAnIPButton = getByText('Add Another IP'); + await userEvent.click(addAnIPButton); expect(addAccessControlsButton).toHaveAttribute('aria-disabled', 'false'); }); diff --git a/packages/manager/src/features/Databases/DatabaseDetail/AddAccessControlDrawer.tsx b/packages/manager/src/features/Databases/DatabaseDetail/AddAccessControlDrawer.tsx index a6f79c07771..4eab8a9c272 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/AddAccessControlDrawer.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/AddAccessControlDrawer.tsx @@ -5,13 +5,22 @@ import { makeStyles } from 'tss-react/mui'; import { ActionsPanel } from 'src/components/ActionsPanel/ActionsPanel'; import { Drawer } from 'src/components/Drawer'; +import { Link } from 'src/components/Link'; import { MultipleIPInput } from 'src/components/MultipleIPInput/MultipleIPInput'; +import { + ACCESS_CONTROLS_DRAWER_TEXT, + ACCESS_CONTROLS_DRAWER_TEXT_LEGACY, + LEARN_MORE_LINK, + LEARN_MORE_LINK_LEGACY, +} from 'src/features/Databases/constants'; +import { isDefaultDatabase } from 'src/features/Databases/utilities'; import { enforceIPMasks } from 'src/features/Firewalls/FirewallDetail/Rules/FirewallRuleDrawer.utils'; import { useDatabaseMutation } from 'src/queries/databases/databases'; import { handleAPIErrors } from 'src/utilities/formikErrorUtils'; import { extendedIPToString, ipFieldPlaceholder, + ipV6FieldPlaceholder, stringToExtendedIP, validateIPs, } from 'src/utilities/ipUtils'; @@ -65,6 +74,8 @@ const AddAccessControlDrawer = (props: CombinedProps) => { database.id ); + const isDefaultDB = isDefaultDatabase(database); + const handleUpdateAccessControlsClick = ( { _allowList }: Values, { @@ -166,8 +177,9 @@ const AddAccessControlDrawer = (props: CombinedProps) => { } }, [open, resetForm]); + const learnMoreLink = isDefaultDB ? LEARN_MORE_LINK : LEARN_MORE_LINK_LEGACY; return ( - + {error ? : null} {allowListErrors @@ -180,11 +192,21 @@ const AddAccessControlDrawer = (props: CombinedProps) => { )) : null} - Add, edit, or remove IPv4 addresses and ranges that should be - authorized to access your cluster. + {isDefaultDB + ? ACCESS_CONTROLS_DRAWER_TEXT + : ACCESS_CONTROLS_DRAWER_TEXT_LEGACY}{' '} + Learn more.
0 + ? 'Add Another IP' + : 'Add an IP' + } + placeholder={ + isDefaultDB ? ipV6FieldPlaceholder : ipFieldPlaceholder + } aria-label="Allowed IP Addresses or Ranges" className={classes.ipSelect} forDatabaseAccessControls @@ -192,8 +214,7 @@ const AddAccessControlDrawer = (props: CombinedProps) => { ips={values._allowList!} onBlur={handleIPBlur} onChange={handleIPChange} - placeholder={ipFieldPlaceholder} - title="Allowed IP Address(es) or Range(s)" + title="Allowed IP Addresses or Ranges" /> = (props) => { const accessControlCopy = ( - Add or remove IPv4 addresses or ranges that should be authorized to access - your cluster. + {!isDefaultDB + ? ACCESS_CONTROLS_IN_SETTINGS_TEXT_LEGACY + : ACCESS_CONTROLS_IN_SETTINGS_TEXT} ); - const suspendClusterCopy = `Suspend the cluster if you don't use it temporarily to prevent being billed for it.`; + const suspendClusterCopy = SUSPEND_CLUSTER_TEXT; const resetRootPasswordCopy = !isDefaultDB - ? 'Resetting your root password will automatically generate a new password. You can view the updated password on your database cluster summary page. ' - : 'Reset your root password if someone should no longer have access to the root user or if you believe your password may have been compromised. This will automatically generate a new password that you’ll be able to see on your database cluster summary page.'; + ? RESET_ROOT_PASSWORD_TEXT_LEGACY + : RESET_ROOT_PASSWORD_TEXT; const deleteClusterCopy = !isDefaultDB - ? 'Deleting a database cluster is permanent and cannot be undone.' - : 'Permanently remove an unused database cluster.'; + ? DELETE_CLUSTER_TEXT_LEGACY + : DELETE_CLUSTER_TEXT; const [isDeleteDialogOpen, setIsDeleteDialogOpen] = React.useState(false); const [ diff --git a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummaryConnectionDetails.tsx b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummaryConnectionDetails.tsx index c59c7ac2b84..c077387da22 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummaryConnectionDetails.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummaryConnectionDetails.tsx @@ -232,7 +232,7 @@ export const DatabaseSummaryConnectionDetails = (props: Props) => { Database name - defaultdb + {isLegacy ? database.engine : 'defaultdb'} Host diff --git a/packages/manager/src/features/Databases/constants.ts b/packages/manager/src/features/Databases/constants.ts new file mode 100644 index 00000000000..0a8fc5e9480 --- /dev/null +++ b/packages/manager/src/features/Databases/constants.ts @@ -0,0 +1,30 @@ +// Various constants for the Databases + +// Copy +export const ACCESS_CONTROLS_DRAWER_TEXT = + 'Add, edit, or remove IPv6 (recommended) or IPv4 addresses or ranges that should be authorized to access your cluster.'; +export const ACCESS_CONTROLS_DRAWER_TEXT_LEGACY = + 'Add, edit, or remove IPv4 addresses and ranges that should be authorized to access your cluster.'; + +export const ACCESS_CONTROLS_IN_SETTINGS_TEXT = + 'Add or remove IPv6 (recommended) or IPv4 addresses or ranges that should be authorized to access your cluster.'; +export const ACCESS_CONTROLS_IN_SETTINGS_TEXT_LEGACY = + 'Add or remove IPv4 addresses or ranges that should be authorized to access your cluster.'; + +export const SUSPEND_CLUSTER_TEXT = `Suspend the cluster if you don't use it temporarily to prevent being billed for it.`; + +export const RESET_ROOT_PASSWORD_TEXT = + 'Reset your root password if someone should no longer have access to the root user or if you believe your password may have been compromised. This will automatically generate a new password that you’ll be able to see on your database cluster summary page.'; +export const RESET_ROOT_PASSWORD_TEXT_LEGACY = + 'Resetting your root password will automatically generate a new password. You can view the updated password on your database cluster summary page. '; + +export const DELETE_CLUSTER_TEXT = + 'Permanently remove an unused database cluster.'; +export const DELETE_CLUSTER_TEXT_LEGACY = + 'Deleting a database cluster is permanent and cannot be undone.'; + +// Links +export const LEARN_MORE_LINK_LEGACY = + 'https://techdocs.akamai.com/cloud-computing/docs/manage-access-controls'; +export const LEARN_MORE_LINK = + 'https://techdocs.akamai.com/cloud-computing/docs/aiven-manage-database#ipv6-support'; diff --git a/packages/manager/src/utilities/ipUtils.ts b/packages/manager/src/utilities/ipUtils.ts index 06392a895a2..f7d773b32e3 100644 --- a/packages/manager/src/utilities/ipUtils.ts +++ b/packages/manager/src/utilities/ipUtils.ts @@ -24,6 +24,7 @@ export interface ExtendedIP { export const stringToExtendedIP = (ip: string): ExtendedIP => ({ address: ip }); export const extendedIPToString = (ip: ExtendedIP): string => ip.address; export const ipFieldPlaceholder = '192.0.2.1/32'; +export const ipV6FieldPlaceholder = '2600:1401:4000::1726:XXXX'; export const IP_ERROR_MESSAGE = 'Must be a valid IPv4 or IPv6 range.';