Skip to content
2 changes: 0 additions & 2 deletions packages/api-v4/src/databases/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,6 @@ type MemberType = 'failover' | 'primary';
export interface DatabaseInstance {
allow_list: string[];
cluster_size: ClusterSize;
/** @Deprecated replaced by `endpoints` property */
connection_pool_port: null | number;
connection_strings: ConnectionStrings[];
created: string;
/** @Deprecated used by rdbms-legacy only, rdbms-default always encrypts */
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/manager": Upcoming Features
---

Use new hostname endpoints in Service URIs and display public/private URIs for public VPCs ([#13439](https://github.com/linode/manager/pull/13439))
10 changes: 2 additions & 8 deletions packages/manager/src/factories/databases.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,6 @@ export const databaseInstanceFactory =
? ([1, 3][i % 2] as ClusterSize)
: ([1, 2, 3][i % 3] as ClusterSize)
),
connection_pool_port:
null /** @Deprecated replaced by `endpoints` property */,
connection_strings: [],
created: '2021-12-09T17:15:12',
encrypted: false,
Expand Down Expand Up @@ -203,9 +201,7 @@ export const databaseInstanceFactory =
members: {
'2.2.2.2': 'primary',
},
platform: Factory.each((i) =>
adb10(i) ? 'rdbms-legacy' : 'rdbms-default'
),
platform: 'rdbms-default',
region: Factory.each((i) => possibleRegions[i % possibleRegions.length]),
status: Factory.each((i) => possibleStatuses[i % possibleStatuses.length]),
type: Factory.each((i) => possibleTypes[i % possibleTypes.length]),
Expand All @@ -230,8 +226,6 @@ export const databaseInstanceFactory =
export const databaseFactory = Factory.Sync.makeFactory<Database>({
allow_list: [...IPv4List],
cluster_size: Factory.each(() => pickRandom([1, 3])),
connection_pool_port:
null /** @Deprecated replaced by `endpoints` property */,
connection_strings: [
{
driver: 'python',
Expand Down Expand Up @@ -277,7 +271,7 @@ export const databaseFactory = Factory.Sync.makeFactory<Database>({
'2.2.2.2': 'primary',
},
oldest_restore_time: '2024-09-15T17:15:12',
platform: Factory.each((i) => (adb10(i) ? 'rdbms-legacy' : 'rdbms-default')),
platform: 'rdbms-default',
private_network: null,
port: 3306,
region: 'us-east',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,23 @@ import { DatabaseConnectionPools } from './DatabaseConnectionPools';
const mockDatabase = databaseFactory.build({
platform: 'rdbms-default',
private_network: null,
hosts: {
primary: 'db-mysql-primary-0.b.linodeb.net',
endpoints: [
{
role: 'primary',
address: 'db-mysql-primary-0.b.linodeb.net',
port: 15847,
public_access: true,
},
{
role: 'primary-connection-pool',
address: 'public-db-mysql-primary-0.b.linodeb.net',
port: 15848,
public_access: true,
},
],
},
engine: 'postgresql',
id: 1,
});
Expand All @@ -30,6 +47,7 @@ const mockConnectionPool = databaseConnectionPoolFactory.build({
const queryMocks = vi.hoisted(() => {
return {
useDatabaseConnectionPoolsQuery: vi.fn(),
useFlags: vi.fn().mockReturnValue({}),
};
});

Expand All @@ -41,6 +59,14 @@ vi.mock('@linode/queries', async () => {
};
});

vi.mock('src/hooks/useFlags', () => {
const actual = vi.importActual('src/hooks/useFlags');
return {
...actual,
useFlags: queryMocks.useFlags,
};
});

describe('DatabaseConnectionPools Component', () => {
beforeEach(() => {
vi.resetAllMocks();
Expand Down Expand Up @@ -109,11 +135,14 @@ describe('DatabaseConnectionPools Component', () => {
expect(errorStateText).toBeInTheDocument();
});

it('should render service URI component if there are connection pools', () => {
it('should render service URI component if there are connection pools and hostnameEndpoints flag is true', () => {
queryMocks.useDatabaseConnectionPoolsQuery.mockReturnValue({
data: makeResourcePage([mockConnectionPool]),
isLoading: false,
});
queryMocks.useFlags.mockReturnValue({
hostnameEndpoints: true,
});

renderWithTheme(<DatabaseConnectionPools database={mockDatabase} />);
const serviceURIText = screen.getByText('Service URI');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
Stack,
Typography,
} from '@linode/ui';
import Grid from '@mui/material/Grid';
import { useTheme } from '@mui/material/styles';
import { Pagination } from 'akamai-cds-react-components/Pagination';
import {
Expand All @@ -28,6 +29,12 @@ import {
CONNECTION_POOL_LABEL_CELL_STYLES,
MANAGE_CONNECTION_POOLS_LEARN_MORE_LINK,
} from 'src/features/Databases/constants';
import {
StyledGridContainer,
StyledLabelTypography,
StyledValueGrid,
} from 'src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummaryClusterConfiguration.style';
import { useFlags } from 'src/hooks/useFlags';
import { usePaginationV2 } from 'src/hooks/usePaginationV2';

import { makeSettingsItemStyles } from '../../shared.styles';
Expand All @@ -47,6 +54,7 @@ interface Props {
export const DatabaseConnectionPools = ({ database }: Props) => {
const { classes } = makeSettingsItemStyles();
const theme = useTheme();
const flags = useFlags();
const isDatabaseInactive = database.status !== 'active';

const [deletePoolLabelSelection, setDeletePoolLabelSelection] =
Expand Down Expand Up @@ -80,6 +88,9 @@ export const DatabaseConnectionPools = ({ database }: Props) => {
);
}

const hasVPC = Boolean(database?.private_network?.vpc_id);
const hasPublicVPC = hasVPC && database.private_network?.public_access;

return (
<>
<div className={classes.topSection}>
Expand Down Expand Up @@ -110,9 +121,42 @@ export const DatabaseConnectionPools = ({ database }: Props) => {
Add Pool
</Button>
</div>
{connectionPools && connectionPools.data.length > 0 && (
<ServiceURI database={database} />
)}
{flags?.hostnameEndpoints &&
connectionPools &&
connectionPools.data.length > 0 && (
<StyledGridContainer container size={12} spacing={0}>
<Grid
size={{
md: 2,
xs: 3,
}}
>
<StyledLabelTypography>
{hasPublicVPC ? 'Public Service URI' : 'Service URI'}
</StyledLabelTypography>
</Grid>
<StyledValueGrid size={{ md: 10, xs: 9 }}>
<ServiceURI database={database} />
</StyledValueGrid>
{hasPublicVPC && (
<>
<Grid
size={{
md: 2,
xs: 3,
}}
>
<StyledLabelTypography>
Private Service URI
</StyledLabelTypography>
</Grid>
<StyledValueGrid size={{ md: 10, xs: 9 }}>
<ServiceURI database={database} showPrivateVPC />
</StyledValueGrid>
</>
)}
</StyledGridContainer>
)}
<div style={{ overflowX: 'auto', width: '100%' }}>
<Table
aria-label={'List of Connection pools'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ import { styled } from '@mui/material/styles';
import * as React from 'react';

import ClusterConfiguration from 'src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummaryClusterConfiguration';
import {
StyledGridContainer,
StyledLabelTypography,
StyledValueGrid,
} from 'src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummaryClusterConfiguration.style';
import ConnectionDetails from 'src/features/Databases/DatabaseDetail/DatabaseSummary/DatabaseSummaryConnectionDetails';
import { useFlags } from 'src/hooks/useFlags';

Expand All @@ -28,6 +33,9 @@ export const DatabaseSummary = () => {
connectionPools &&
connectionPools.data.length > 0;

const hasVPC = Boolean(database?.private_network?.vpc_id);
const hasPublicVPC = hasVPC && database.private_network?.public_access;

return (
<Paper>
<Grid container spacing={2}>
Expand All @@ -47,7 +55,7 @@ export const DatabaseSummary = () => {
>
<ConnectionDetails database={database} />
</Grid>
{showPgBouncerConnectionDetails && (
{flags.hostnameEndpoints && showPgBouncerConnectionDetails && (
<Grid
size={{
md: 12,
Expand All @@ -57,7 +65,38 @@ export const DatabaseSummary = () => {
<Typography mb={2} variant="h3">
PgBouncer Connection Details
</Typography>
<ServiceURI database={database} />
<StyledGridContainer container size={12} spacing={0}>
<Grid
size={{
md: 2,
xs: 3,
}}
>
<StyledLabelTypography>
{hasPublicVPC ? 'Public Service URI' : 'Service URI'}
</StyledLabelTypography>
</Grid>
<StyledValueGrid size={{ md: 10, xs: 9 }}>
<ServiceURI database={database} />
</StyledValueGrid>
{hasPublicVPC && (
<>
<Grid
size={{
md: 2,
xs: 3,
}}
>
<StyledLabelTypography>
Private Service URI
</StyledLabelTypography>
</Grid>
<StyledValueGrid size={{ md: 10, xs: 9 }}>
<ServiceURI database={database} showPrivateVPC />
</StyledValueGrid>
</>
)}
</StyledGridContainer>
</Grid>
)}
</Grid>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,17 +117,32 @@ export const DatabaseSummaryConnectionDetails = (props: Props) => {
</>
);

const hasPublicVPC = hasVPC && database.private_network?.public_access;
const showServiceURIs = flags.hostnameEndpoints && flags.databasePgBouncer;

return (
<>
<Typography className={classes.header} variant="h3">
Connection Details
</Typography>
<StyledGridContainer container size={{ lg: 10, md: 10 }} spacing={0}>
{flags.databasePgBouncer && (
<ConnectionDetailsRow isSummaryTab label="Service URI">
{showServiceURIs && (
<ConnectionDetailsRow
isSummaryTab
label={`${hasPublicVPC ? 'Public Service URI' : 'Service URI'} `}
>
<ServiceURI database={database} isGeneralServiceURI />
</ConnectionDetailsRow>
)}
{showServiceURIs && hasPublicVPC && (
<ConnectionDetailsRow isSummaryTab label="Private Service URI">
<ServiceURI
database={database}
isGeneralServiceURI
showPrivateVPC={true}
/>
</ConnectionDetailsRow>
)}
<ConnectionDetailsRow isSummaryTab label="Username">
{username}
</ConnectionDetailsRow>
Expand Down
Loading